Mengapa orang merekomendasikan untuk tidak menggunakan nama "Id" untuk kolom identitas?

68

Saya diajari untuk tidak menggunakan nama Iduntuk kolom identitas tabel saya, tetapi belakangan ini saya baru saja menggunakannya karena itu sederhana, pendek, dan sangat deskriptif tentang apa sebenarnya data tersebut.

Saya telah melihat orang menyarankan awalan Iddengan nama tabel, tetapi ini sepertinya membuat lebih banyak pekerjaan untuk orang yang menulis pertanyaan SQL (atau programmer jika Anda menggunakan ORM seperti Entity Framework), terutama pada nama tabel yang lebih panjang seperti CustomerProductIdatauAgencyGroupAssignementId

Satu vendor pihak ketiga yang kami sewa untuk menciptakan sesuatu untuk kami sebenarnya menamai semua kolom identitas mereka Identhanya untuk menghindari penggunaan Id. Pada awalnya saya pikir mereka melakukan itu karena Idkata kunci, tetapi ketika saya melihatnya, saya menemukan itu Idbukan kata kunci dalam SQL Server 2005, yang kami gunakan.

Jadi mengapa orang merekomendasikan untuk tidak menggunakan nama Iduntuk kolom identitas?

Sunting: Untuk memperjelas, saya tidak meminta konvensi penamaan mana yang akan digunakan, atau untuk argumen untuk menggunakan satu konvensi penamaan di atas yang lain. Saya hanya ingin tahu mengapa disarankan untuk tidak menggunakan Idnama kolom identitas.

Saya seorang programmer tunggal, bukan dba, dan bagi saya database hanyalah tempat untuk menyimpan data saya. Karena saya biasanya membuat aplikasi kecil, dan biasanya menggunakan ORM untuk akses data, nama bidang umum untuk bidang identitas jauh lebih mudah untuk dikerjakan. Saya ingin tahu apa yang saya lewatkan dengan melakukan ini, dan jika ada alasan yang sangat baik bagi saya untuk tidak melakukan ini.

Rachel
sumber
10
BF bunfight di sini sudah: programmers.stackexchange.com/q/114728/5905 Beberapa dari kita (baca: saya) tersedot ke dalamnya ...
gbn
Apakah benar-benar ada aturan yang melarang penggunaan "id" sebagai nama kolom identitas? ActiveRecord, ORM standar untuk Ruby on Rails, melakukan hal itu dengan konvensi. ar.rubyonrails.org
200_success
1
@ 200_sukses Di tingkat basis data, ya. Ini situs database, bukan situs ORM;)
JNK
2
Juga, untuk SQL Server secara khusus, lihat dba.stackexchange.com/questions/124655/… dan, lebih khusus lagi, connect.microsoft.com/SQLServer/feedback/details/2178150
Aaron Bertrand

Jawaban:

46

Awalan nama tabel memiliki alasan yang sangat bagus.

Mempertimbangkan:

TableA (id int identity, stringdata varchar(max))

TableB (id int identity, stringdata varchar(max))

Kami ingin DELETEdari TableAcatatan yang ada di kedua tabel. Cukup mudah, kami hanya akan melakukan INNER JOIN:

DELETE a
FROM 
  TableA A
INNER JOIN 
  TableB B
    ON b.id = B.id

.... dan kami baru saja memusnahkan semua TableA. Kami secara tidak sengaja membandingkan ID B dengan dirinya sendiri - setiap catatan cocok, dan setiap catatan dihapus.

Jika bidang telah dinamai TableAIddan TableBIdini tidak mungkin ( Invalid field name TableAid in TableB).

Secara pribadi saya tidak punya masalah dengan menggunakan nama iddalam sebuah tabel, tapi itu benar-benar praktik yang lebih baik untuk mengawali dengan nama tabel (atau nama entitas, jika TableAorang-orang maka PeopleIdakan bekerja dengan baik juga) untuk menghindari secara tidak sengaja membandingkan dengan bidang yang salah dan meniup sesuatu terjadi.

Ini juga membuatnya sangat jelas dari mana bidang berasal dari pertanyaan panjang dengan banyak JOINs.

JNK
sumber
10
Jadi pada dasarnya ini adalah konvensi penamaan untuk melindungi dari kesalahan? Saya akan berpikir menggunakan begin transactiondan commit transactionakan menjadi praktik yang lebih baik daripada menggunakan (imo) skema penamaan yang lebih menjengkelkan
Rachel
13
@ Rachel: ini untuk 1. kejelasan 2. menghindari alias kolom yang tidak perlu 3. izinkan GABUNG .. MENGGUNAKAN 4. mengganggu monyet PHP yang bekerja dalam objek tunggal, bukan set
gbn
4
@Rachel Jika Anda tidak melihat kesalahan saat menulis kueri, dan tepat sebelum Anda mengeksekusinya, sepertinya Anda tidak akan melihatnya sebelum melakukan. Hal ini terjadi, mengapa membuatnya lebih mungkin?
Andy
7
@Andy Saya selalu melakukan SELECTuntuk menemukan catatan saya sebelum saya menjalankan DELETE, dan begitu saya menjalankan pernyataan saya selalu memverifikasi bahwa jumlah baris adalah apa yang saya harapkan sebelum melakukan.
Rachel
5
@Rachel Bagus sekali bahwa Anda memiliki sesuatu yang bekerja untuk Anda. Bisakah Anda membuat semua orang melakukan itu?
Andy
36

Sebagian besar untuk menjaga kunci asing dari menjadi sakit luar biasa. Katakanlah Anda memiliki dua tabel: Pelanggan dan Alamat Pelanggan. Kunci utama untuk keduanya adalah kolom bernama id, yang merupakan kolom identitas (int).

Sekarang Anda harus memiliki ID pelanggan yang dirujuk dari CustomerAddress. Anda tidak bisa memberi nama id kolom, jadi Anda menggunakan customer_id.

Ini mengarah pada beberapa masalah. Pertama, Anda harus secara konsisten mengingat kapan memanggil kolom "id", dan kapan menyebutnya "customer_id". Dan jika Anda mengacaukannya, ini mengarah ke masalah kedua. Jika Anda punya pertanyaan besar dengan sekitar selusin bergabung, dan itu tidak mengembalikan data apa pun, bersenang-senang bermain Di mana Waldo dan memburu kesalahan ketik ini:

ON c.id = ca.id

Ups, seharusnya ON c.id = ca.customer_id. Atau lebih baik lagi, beri nama kolom identitas Anda secara deskriptif, sehingga bisa ON c.customer_id = ca.customer_id. Kemudian jika Anda secara tidak sengaja menggunakan alias tabel yang salah di suatu tempat, customer_id tidak akan menjadi kolom dalam tabel itu, dan Anda akan mendapatkan kesalahan kompilasi yang bagus, daripada hasil kosong dan menyipitkan kode berikutnya.

Memang, ada kasus-kasus di mana ini tidak membantu, seperti jika Anda memerlukan beberapa hubungan kunci asing dari satu tabel ke tabel tunggal lainnya, tetapi penamaan semua kunci utama "id" juga tidak membantu.

db2
sumber
27

Berikut adalah ringkasan dari semua jawaban tentang keuntungan yang diperoleh dari konvensi untuk tidak menggunakan nama umum untuk semua kunci utama:

  • Lebih sedikit kesalahan, karena bidang identitas tidak bernama sama

    Anda tidak dapat secara keliru menulis kueri yang bergabung B.Id = B.Idsebagai gantinya A.Id = B.Id, karena bidang identitas tidak akan pernah dinamai sama persis.

  • Nama kolom yang lebih jelas.

    Jika Anda melihat kolom bernama CustomerId, Anda segera tahu data apa yang ada di kolom itu. Jika nama kolom itu seperti sesuatu yang generik Id, maka Anda perlu mengetahui nama tabel juga untuk mengetahui data apa yang dikandung kolom tersebut.

  • Hindari alias kolom yang tidak perlu

    Sekarang Anda dapat menulis SELECT CustomerId, ProductIddari kueri yang bergabung Customersdengan Products, alih-alihSELECT Customer.Id as CustomerId, Products.Id as ProductId

  • Mengizinkan JOIN..USINGsintaksis

    Anda dapat bergabung dengan tabel dengan sintaks Customer JOIN Products USING (CustomerId), alih-alihCustomer JOIN Products ON Customer.Id = Products.Id

  • Kuncinya lebih mudah ditemukan dalam pencarian

    Jika Anda mencari bidang identitas pelanggan dalam solusi besar, mencari CustomerIdjauh lebih berguna daripada mencariId

Jika Anda dapat memikirkan kelebihan lain yang dimiliki oleh konvensi penamaan ini, beri tahu saya dan saya akan menambahkannya ke daftar.

Apakah Anda memilih untuk menggunakan nama kolom yang unik atau identik untuk bidang identitas terserah Anda, tetapi terlepas dari apa yang Anda pilih, harap konsisten :)

Rachel
sumber
12

Untuk menyalin jawaban saya dari pertanyaan yang ditautkan:

Ada situasi di mana menempelkan "ID" di setiap tabel bukan ide terbaik: USINGkata kunci, jika didukung. Kami sering menggunakannya di MySQL.

Misalnya, jika Anda memiliki fooTabledengan kolom fooTableIddan barTabledengan kunci asing fooTableId, maka pertanyaan Anda dapat dibuat seperti itu:

SELECT fooTableId, fooField1, barField2 FROM fooTable INNER JOIN barTable USING (fooTableId)

Ini tidak hanya menghemat pengetikan, tetapi jauh lebih mudah dibaca dibandingkan dengan alternatif:

SELECT fooTable.Id, fooField1, barField2 FROM fooTable INNER JOIN barTable ON (fooTable.Id = barTable.foTableId)
Izkata
sumber
9

Setelah menormalkan skema database untuk membatasi redundansi, tabel dibagi dalam tabel yang lebih kecil dengan hubungan yang sudah ada (satu ke satu, satu ke banyak, banyak ke banyak). Dalam proses, satu bidang dalam tabel asli dapat muncul dalam beberapa tabel yang dinormalisasi.

Misalnya, basis data untuk blog bisa terlihat seperti ini dalam bentuknya yang tidak dinormalisasi, dengan asumsi kendala unik pada Author_Nickname.

| Author_Nickname | Author_Email | Post_Title | Post_Body |
+-----------------+--------------+------------+-----------+
| dave            | dave@x.com   | Blah       | Bla bla   |
| dave            | dave@x.com   | Stuff      | I like    |
| sophie          | s@oph.ie     | Lorem      | Ipsum     |

Normalisasi akan menghasilkan dua tabel:

Penulis:

| Author_Nickname | Author_Email |
+-----------------+--------------+
| dave            | dave@x.com   |
| sophie          | s@oph.ie     |

Pos

| Author_Nickname | Post_Title | Post_Body |
+-----------------+------------+-----------+
| dave            | Blah       | Bla bla   |
| dave            | Stuff      | I like    |
| sophie          | Lorem      | Ipsum     |

Di sini Author_Nickname akan menjadi kunci utama untuk tabel penulis, dan kunci asing di tabel posting. Bahkan jika Author_Nickname muncul dalam dua tabel, itu tetap berhubungan dengan satu unit informasi, yaitu. setiap nama kolom sesuai dengan satu bidang .

Dalam banyak kasus tidak mungkin ada kendala unik pada bidang asli, jadi bidang buatan numerik digunakan sebagai kunci utama. Ini tidak mengubah fakta bahwa setiap nama kolom masih mewakili satu bidang. Dalam desain database tradisional, nama-nama kolom individu sesuai dengan bidang tunggal bahkan jika mereka bukan kunci. (misalnya, seseorang akan menggunakan part.partname dan client.clientname daripada part.name dan client.name ). Ini adalah alasan keberadaan INNER JOIN ... USING <key>dan NATURAL JOINsintaksis.

Namun, saat ini, dan dengan lapisan ORM tersedia dalam banyak bahasa, basis data sering dirancang sebagai lapisan ketahanan untuk bahasa OO, di mana variabel yang memiliki peran yang sama di kelas yang berbeda disebut sama ( part.name dan client.name , bukan part.partname dan client.clientname ). Dalam konteks seperti itu, saya cenderung menggunakan 'ID' untuk kunci utama saya.

stilgar
sumber
7

Satu vendor pihak ketiga yang kami sewa untuk membuat sesuatu untuk kami sebenarnya menamai semua kolom identitas mereka Ident hanya untuk menghindari penggunaan Id.

Menggunakan "Ident" bukannya "Id" tidak benar-benar menyelesaikan apa pun jika "Ident" akhirnya digunakan di semua tabel mereka.

Ada artikel yang bagus tentang konvensi kode SQL di situs Drupal yang menunjukkan praktik yang baik untuk situasi ini:

Ini adalah praktik yang baik untuk awalan nama tabel dengan nama modul untuk mencegah kemungkinan konflik namespace.

Dari sudut pandang ini, CustomerProductId dan AgencyGroupAssignmentId masuk akal untuk digunakan. Ya, itu sangat verbose. Anda dapat mempersingkatnya, tetapi poin terbesar yang harus diperhatikan adalah apakah pengembang yang mengikuti Anda akan memahami apa yang Anda maksudkan . Id diawali dengan nama tabel verbose seharusnya tidak meninggalkan ambiguitas seperti apa mereka. Dan (bagi saya) itu lebih penting daripada menyimpan beberapa penekanan tombol.

Harun
sumber
7

Saya menamai kolom saya CustomerID bukan ID, jadi setiap kali saya mengetik

FROM dbo.Customers AS c JOIN dbo.CustomerOrders AS o

SQL Prompt segera menyarankan yang berikut ini

ON c.CustomerID = o.CustomerID 

Ini menghemat beberapa penekanan tombol. Namun saya pikir konvensi penamaan sangat subyektif dan karena itu saya tidak memiliki pendapat yang kuat.

AK
sumber
5

Itu alasan yang sama mengapa Anda tidak akan memberi nama semua bidang varchar Anda seperti "UserText" dan "UserText1", atau mengapa Anda tidak akan menggunakan "UserDate" dan "UserDate1".

Biasanya jika Anda memiliki bidang identitas dalam tabel itu adalah kunci utama Anda. Bagaimana Anda membangun tabel anak dengan kunci asing ke tabel induk jika kunci utama di kedua tabel adalah id?

Tidak semua orang setuju dengan metode ini, tetapi dalam database saya, saya memberikan singkatan unik untuk setiap tabel. PK untuk tabel itu akan diberi nama ID PK_ [abbrv]. JIKA itu digunakan sebagai FK di mana saja maka saya akan menggunakan ID FK_ [abbrv]. Sekarang saya punya nol menebak bekerja pada mencari tahu apa hubungan tabel itu.

DForck42
sumber
5

Pada dasarnya untuk alasan yang sama Anda biasanya tidak menamai parameter parameter1, parameter2 ... itu akurat, tetapi tidak deskriptif. Jika Anda melihat TableId, maka Anda mungkin dapat dengan aman berasumsi bahwa itu digunakan untuk memegang pk untuk Table, terlepas dari konteksnya.

Adapun siapa pun yang menggunakan Ident, ia sepenuhnya melewatkan poin, diberi pilihan antara Ident dan Id use Id. Ident bahkan lebih membingungkan daripada ID.

Di luar konteks, Id dapat dianggap sebagai kunci utama untuk beberapa tabel (tidak terlalu berguna kecuali id ​​adalah panduan), tetapi Ident bahkan tidak memberi tahu Anda (atau setidaknya saya) itu. Saya akhirnya akan mengetahui bahwa Ident adalah kependekan dari identitas (satu atau lain cara), tetapi waktu yang saya habiskan untuk mencari tahu akan sia-sia.

jmoreno
sumber
3

Gunakan awalan sehingga nama yang sama dapat digunakan dalam konteks kunci utama dan kunci asing, sehingga Anda dapat melakukan natural join/ join ... using.

DrPizza
sumber