Konvensi penamaan kunci utama / kunci asing [ditutup]

97

Dalam grup pengembang kami, kami memiliki perdebatan sengit mengenai konvensi penamaan untuk Kunci Utama dan Kunci Asing. Pada dasarnya ada dua aliran pemikiran dalam kelompok kami:

1:

Primary Table (Employee)   
Primary Key is called ID

Foreign table (Event)  
Foreign key is called EmployeeID

atau

2:

Primary Table (Employee)  
Primary Key is called EmployeeID

Foreign table (Event)  
Foreign key is called EmployeeID

Saya memilih untuk tidak menduplikasi nama tabel di salah satu kolom (Jadi saya lebih suka opsi 1 di atas). Secara konseptual, ini konsisten dengan banyak praktik yang direkomendasikan dalam bahasa lain, di mana Anda tidak menggunakan nama objek dalam nama propertinya. Saya pikir penamaan kunci asing EmployeeID(atau Employee_IDmungkin lebih baik) memberitahu pembaca bahwa itu adalah IDkolom EmployeeTabel.

Beberapa yang lain lebih memilih opsi 2 di mana Anda memberi nama kunci utama diawali dengan nama tabel sehingga nama kolomnya sama di seluruh database. Saya mengerti hal itu, tetapi Anda sekarang tidak dapat secara visual membedakan kunci utama dari kunci asing.

Juga, saya pikir itu berlebihan untuk memiliki nama tabel di nama kolom, karena jika Anda menganggap tabel sebagai entitas dan kolom sebagai properti atau atribut dari entitas itu, Anda menganggapnya sebagai atribut ID dari Employee, bukan yang EmployeeIDatribut seorang karyawan. Aku tidak pergi dan meminta rekan kerja saya apa nya PersonAgeatau PersonGenderyang. Saya bertanya padanya berapa Umurnya.

Jadi seperti yang saya katakan, ini adalah debat yang sengit dan kami terus-menerus membahasnya. Saya tertarik untuk mendapatkan perspektif baru.

Jeremy
sumber
1
pertanyaan menggandakan stackoverflow.com/questions/208580/…
Mike Henke
1
Saya membaca lebih dari 10 pertanyaan serupa dan akhirnya menemukan 3 jawaban teratas di sini bagus: stackoverflow.com/a/465146/781695
pengguna
Sekadar catatan: Pilihan 2 akan memungkinkan Anda untuk 'Bergabung Secara Alami'. Heck, kenapa tidak tetap lakukan di pilihan 1 dengan menambahkan 'Employee.ID as EmployeeID'. Tetapi cara praktik yang lebih baik tampaknya adalah 'Gabung' menggunakan 'ON Employee.ID = Event.EmployeeID'.
Leo
Dalam kedua situasi, Anda akan dan yang lebih tinggi harus menggunakan alias (atau 'table_name.column_name') dalam satu atau lebih antrian karena Anda, dalam kedua kasus, mengulangi nama kolom.
Please_Dont_Bully_Me_SO_Lords

Jawaban:

52

Itu tidak terlalu penting. Saya tidak pernah menemukan sistem di mana ada perbedaan nyata antara pilihan 1 dan pilihan 2.

Jeff Atwood memiliki artikel bagus beberapa waktu lalu tentang topik ini. Pada dasarnya orang-orang memperdebatkan dan memperdebatkan dengan sangat sengit topik-topik yang tidak dapat mereka buktikan salah. Atau dari sudut yang berbeda, topik-topik yang hanya dapat dimenangkan melalui argumen last-man-standing berbasis ketahanan gaya filibuster.

Pilih satu dan beri tahu mereka untuk fokus pada masalah yang benar-benar memengaruhi kode Anda.

EDIT: Jika Anda ingin bersenang-senang, minta mereka menentukan secara panjang lebar mengapa metode mereka lebih baik untuk referensi tabel rekursif.

Russell Steen
sumber
27
+1, untuk akal sehat ... Ada hal yang lebih penting untuk diperdebatkan .. Jadi, lakukan dengan cara saya (pilihan 2)
Charles Bretana
5
Dan, untuk DRI yang merujuk sendiri, jika ada lebih dari satu FK yang mereferensikan sendiri PK yang sama, Anda HARUS melanggar kedua "standar", karena kedua kolom FK tidak dapat diberi nama yang sama ... misalnya, EmployeeTable dengan EmployeeId PK, SupervisorId FK, MentorId Fk, PartnerId FK, dll ...
Charles Bretana
75

Jika dua kolom memiliki nama yang sama di kedua tabel (konvensi # 2), Anda dapat menggunakan sintaks USING di SQL untuk menghemat beberapa pengetikan dan kebisingan boilerplate:

SELECT name, address, amount
  FROM employees JOIN payroll USING (employee_id)

Argumen lain yang mendukung konvensi # 2 adalah cara model relasional dirancang.

Signifikansi setiap kolom disampaikan sebagian dengan menamainya dengan nama domain yang sesuai.

Steven Huwig
sumber
4
Sintaks dan semantik SQL sebenarnya memberikan petunjuk yang cukup bagus tentang bagaimana itu harus digunakan. misalnya MENGGUNAKAN sintaks berarti kolom dengan domain yang sama harus memiliki nama yang sama, NULL = NULL -> NULL berarti NULL adalah "tidak diketahui" daripada "tidak berlaku", dan ON UPDATE CASCADE berarti bahwa kunci hanya perlu unik, tidak dapat diubah.
Steven Huwig
6
Bahkan lebih baik, memungkinkan ini: SELECT name, address, amount FROM employees NATURAL JOIN payroll.
onedaywhen
5
Saya tidak akan menggunakan gabungan alami dalam kode yang diterapkan, karena lebih rapuh dalam kasus penambahan skema. Tapi untuk kueri interaktif, itu bagus.
Steven Huwig
3
+1 tetapi selalu ada pengecualian. Misalnya, jika Anda memiliki dua kolom dalam penggajian yang keduanya merupakan kunci asing untuk karyawan (satu referensi untuk orang yang dibayar, yang kedua untuk manajer dengan otoritas anggaran, misalnya). Tapi kami tidak bisa menyebutkan kedua kunci asing tersebut employee_id.
Bill Karwin
1
Kata kunci "menggunakan" khusus untuk MySql. Tidak berfungsi di T-SQL — sayangnya.
birdus
12

Saya pikir itu tergantung pada bagaimana Anda menyusun aplikasi. Jika Anda menggunakan ORM atau mendesain tabel Anda untuk merepresentasikan objek, maka opsi 1 mungkin cocok untuk Anda.

Saya suka mengkodekan database sebagai lapisannya sendiri. Saya mengontrol semuanya dan aplikasi hanya memanggil prosedur yang tersimpan. Sangat menyenangkan memiliki kumpulan hasil dengan nama kolom yang lengkap, terutama ketika ada banyak tabel yang digabungkan dan banyak kolom yang dikembalikan. Dengan jenis aplikasi ini, saya suka opsi 2. Saya sangat suka melihat nama kolom yang cocok saat bergabung. Saya telah mengerjakan sistem lama di mana mereka tidak cocok dan itu adalah mimpi buruk,

KM.
sumber
4
+1 karena harus mencari tahu bergabung dengan nama kolom yang tidak cocok
Raj More
4
pada "sistem lama" cacat dari 8 karakter nama panjang yang menyakitkan lebih dari ini. Saya bersedia mengambil risiko dan berspekulasi bahwa memiliki PK bernama ID bukanlah penyebab utama mimpi buruk di sistem lama yang Anda hadapi. Juga "tersedot di sistem lama" digunakan terlalu sering dalam pengembangan perangkat lunak, terutama database. Saya secara rutin melihat orang-orang membenarkan latihan A yang diberikan, berdasarkan cara kerjanya menurut pengalaman mereka pada sistem DB yang dirilis 10+ tahun yang lalu.
Russell Steen
2
hari ini keadaan seni aplikasi akan omong kosong tua dalam beberapa tahun. Anda bahkan mungkin menulis ulang antarmuka, atau menggunakan data di platform lain, tetapi data Anda (termasuk nama kolom Anda) harus bertahan dalam ujian waktu.
KM.
2
Jadi, orang-orang 20 tahun yang lalu seharusnya menggunakan nama kolom yang masuk akal saat ini, meskipun mereka hanya memiliki 8 karakter? Format penyimpanan data telah berubah secara drastis selama 20 tahun terakhir, dan akan berubah lagi dalam 20 tahun mendatang. Tidak ada cara untuk menunjukkan bahwa preferensi Anda akan bertahan dalam ujian waktu lebih baik daripada metode lain yang terdaftar. "nama kolom" sendiri mungkin menjadi "omong kosong lama" pada saat orang-orang mengadakan diskusi ini dalam 20 tahun, karena kemampuan kita untuk menyimpan dan memanipulasi data meningkat. Tabel adalah konstruksi manusia yang merepresentasikan hubungan data secara tidak sempurna ...
Russell Steen
1
Terima kasih atas tanggapan intelektual yang beralasan.
Russell Steen
3

Tidak ada konvensi yang berfungsi di semua kasus, jadi mengapa harus memilikinya? Gunakan Akal Sehat ...

misalnya, untuk tabel referensi mandiri, jika terdapat lebih dari satu kolom FK yang mereferensikan sendiri PK tabel yang sama, Anda HARUS melanggar kedua "standar", karena dua kolom FK tidak dapat diberi nama yang sama ... misalnya , EmployeeTable dengan EmployeeId PK, SupervisorId FK, MentorId Fk, PartnerId FK, ...

Charles Bretana
sumber
1
1 untuk jawaban tujuan teknis aktual
DVK
Jawaban yang bagus dan dapat diterapkan, tetapi argumen untuk jawaban Dems kehilangan intinya.
JYelton
3

Saya setuju bahwa hanya sedikit yang bisa dipilih di antara mereka. Bagi saya hal yang jauh lebih penting tentang kedua standar adalah bagian "standar".

Jika orang mulai 'melakukan hal mereka sendiri', mereka harus digantung oleh nether mereka. MENURUT OPINI SAYA :)

MatBailie
sumber
3
+1 untuk mengakui bahwa konsistensi lebih penting daripada menjadi "benar" (dalam hal ini)
Russell Steen
-1 untuk mencoba menerapkan "konsistensi yang bodoh". Pepatah Cina kuno mengatakan "Konsistensi yang bodoh adalah hobgoblin untuk pikiran yang sederhana."
Charles Bretana
@charles: di dunia di mana orang-orang yang berbeda memelihara kode satu sama lain, seringkali ketika penulis telah pergi dan dokumentasinya sudah usang atau tidak ada, ini bukanlah konsistensi yang bodoh. Saya sangat senang saya tidak bekerja dengan-Mu ...
MatBailie
@Dems, tidak bermaksud menyinggung, tapi ini bodoh, karena dua alasan. 1) Ada skenario umum yang dipahami dengan jelas di mana standar APA PUN HARUS dilanggar. (lihat jawaban saya untuk contoh dan 2) karena dalam masalah ini, setidaknya, standar akan menambah nilai yang sangat kecil, kecuali untuk membuat orang yang menyukai standar merasa lebih nyaman ...
Charles Bretana
1
Anda bisa berargumen bahwa "ID" lebih konsisten - karena begitu Anda memperkenalkan bahasa Inggris "carID" dalam tabel "mobil" atau tabel "mobil"? "sheepID" dalam tabel "sheep" atau "domba" - hal-hal mulai menjadi tidak konsisten. Jika Anda tetap menggunakan "ID" dan nama tabel tunggal - ini tidak hanya konsisten, juga
berfungsi
3

Sudahkah Anda mempertimbangkan hal-hal berikut?

Primary Table (Employee)   
Primary Key is PK_Employee

Foreign table (Event)  
Foreign key is called FK_Employee
Wouter
sumber
3
Saya tidak tahan ketika orang-orang memilih dan tidak memberikan alasan mengapa. Ini adalah jawaban yang sepenuhnya valid, apakah cocok atau tidak bagi beberapa orang adalah pertanyaan yang berbeda, tetapi itu subjektif dan tidak memerlukan suara rendah.
Jeremy
1
Terima kasih telah menunjukkan hal ini. Saya juga tertarik dengan alasan mengapa Anda tidak akan menggunakan format ini. Dan saya yakin akan ada alasan bagus ...
Wouter
Ini adalah jalan keluar terbaik karena Anda tidak perlu menggunakan table_name.column_namekueri dan tidak perlu menggunakan alias untuk nama kolom jika tidak memiliki nama yang berulang ...
Please_Dont_Bully_Me_SO_Lords
1
Ini bisa dianggap sebagai bentuk notasi Hongaria. Jadi pertimbangkan argumen yang mendukung dan menentang itu.
Fred
2

Konvensi yang kami gunakan di tempat saya bekerja hampir sama dengan A, dengan pengecualian bahwa kami memberi nama tabel dalam bentuk jamak (yaitu, "karyawan") dan menggunakan garis bawah antara nama tabel dan kolom. Manfaatnya adalah merujuk ke kolom, bisa berupa "karyawan _ id" atau "karyawan.id", tergantung bagaimana Anda ingin mengaksesnya. Jika Anda perlu menentukan dari tabel mana kolom tersebut berasal, "employee.employees _ id" jelas berlebihan.

Jarett Millard
sumber
Saya belum memutuskan apakah saya suka nama tabel jamak. Dengan menggunakan bentuk tunggal, kueri tampaknya terbaca lebih baik ("nama.pekerjaan" dibandingkan dengan "nama.pekerjaan"). Bahkan dalam gabungan tampaknya membaca lebih baik saat Anda menggabungkan catatan tunggal ke tabel lain. Tapi nama tabel yang jamak tampaknya lebih akurat saat memikirkan tabel, daripada kueri. Saya akan tetap menggunakan singular karena itulah yang kami gunakan, tetapi saya pikir itu juga cara yang tepat untuk pergi (meskipun sekali lagi, banyak yang tidak setuju)
MatBailie
Ya. Ini lebih merupakan preferensi pribadi dan / atau apa pun yang biasa Anda lihat, saya kira.
Jarett Millard
2

Jika Anda melihat kode aplikasi, bukan hanya kueri database, beberapa hal tampak jelas bagi saya:

  1. Definisi tabel biasanya langsung dipetakan ke kelas yang mendeskripsikan satu objek, sehingga harus tunggal. Untuk mendeskripsikan koleksi suatu objek, saya biasanya menambahkan "Array" atau "List" atau "Collection" ke nama tunggal, karena lebih jelas daripada penggunaan jamak menunjukkan tidak hanya bahwa itu adalah koleksi, tetapi juga jenis koleksi apa ini. Dalam tampilan itu, saya melihat nama tabel bukan nama dari koleksi, tetapi nama jenis objek yang merupakan koleksi. Seorang DBA yang tidak menulis kode aplikasi mungkin melewatkan poin ini.

  2. Data yang saya tangani sering kali menggunakan "ID" untuk tujuan identifikasi non-kunci. Untuk menghilangkan kebingungan antara kunci "ID" dan "ID" non-kunci, untuk nama kunci utama, kami menggunakan "Key" (itu maksudnya, bukan?) Diawali dengan nama tabel atau singkatan dari nama tabel. Awalan ini (dan saya mencadangkan ini hanya untuk kunci utama) membuat nama kunci unik, yang sangat penting karena kami menggunakan nama variabel yang sama dengan nama kolom database, dan sebagian besar kelas memiliki induk, yang diidentifikasi dengan nama kunci orang tua. Ini juga diperlukan untuk memastikan bahwa ini bukan kata kunci yang dipesan, yang mana hanya "Kunci" saja. Untuk memfasilitasi agar nama variabel kunci tetap konsisten, dan untuk menyediakan program yang melakukan gabungan alami, kunci asing memiliki nama yang sama seperti yang digunakan dalam tabel di mana mereka adalah kunci utama. Saya memiliki lebih dari sekali program yang bekerja jauh lebih baik dengan cara ini menggunakan gabungan alami. Pada poin terakhir ini, saya mengakui masalah dengan tabel referensi mandiri, yang telah saya gunakan. Dalam hal ini, saya akan membuat pengecualian untuk aturan penamaan kunci asing. Misalnya, saya akan menggunakan ManagerKey sebagai kunci asing di tabel Karyawan untuk menunjuk ke rekaman lain di tabel itu.

Bruce Patin
sumber
Banyak pemeta objek-relasional (ORM) seperti Entity Framework memungkinkan Anda memetakan tabel ke kelas dengan nama berbeda. Ini memungkinkan Anda untuk memiliki kelas bernama "Pengguna" dan tabel bernama "Pengguna".
Fred
2

Saya suka konvensi # 2 - dalam meneliti topik ini, dan menemukan pertanyaan ini sebelum memposting pertanyaan saya sendiri, saya mengalami masalah di mana:

Saya memilih * dari tabel dengan sejumlah besar kolom dan menggabungkannya ke tabel kedua yang juga memiliki banyak kolom. Kedua tabel memiliki kolom "id" sebagai kunci utama, dan itu berarti saya harus secara spesifik memilih setiap kolom (sejauh yang saya tahu) untuk membuat kedua nilai tersebut unik dalam hasil, yaitu:

SELECT table1.id AS parent_id, table2.id AS child_id

Meskipun menggunakan konvensi # 2 berarti saya masih akan memiliki beberapa kolom dalam hasil dengan nama yang sama, sekarang saya dapat menentukan id mana yang saya perlukan (orang tua atau anak) dan, seperti yang disarankan Steven Huwig, USINGpernyataan tersebut menyederhanakan lebih lanjut.

JYelton
sumber
2
SELECT *adalah larangan untuk (sebagian besar) kueri produksi, jadi itu bukan alasan untuk memilih standar penamaan.
P Daddy
1
Tidak tidak setuju: dapatkah Anda memberikan tautan ke alasan mengapa demikian? Saya tidak suka gagasan harus mempertahankan nama dari 80 kolom dalam kueri saya.
JYelton
Tidak dapat menemukan tautan saat ini (sulit dicari di Google untuk "*"), tetapi saya akan menjelaskan poin-poin dasarnya: (1) perubahan pada tabel dapat berdampak negatif pada aplikasi Anda, (2) bisa jadi buruk untuk kinerja, dan (3) menentukan secara eksplisit data apa yang sebenarnya Anda butuhkan dapat membuat kode Anda lebih mudah dipahami. Poin-poin ini bisa meluas, dan ada pengecualian (seperti yang saya singgung) tetapi itu tidak sesuai di sini. Jika Anda memposting ini sebagai pertanyaan baru, saya (dan lainnya) dengan senang hati akan menjelaskan lebih lanjut.
P Daddy
2
Saya mungkin melakukan itu. Saya menyadari manfaat kinerja, tetapi harus mempertimbangkan investasi waktu saat mengedit kode. Saya selalu mencari cara untuk meningkatkan interaksi antara aplikasi dan database. Terima kasih.
JYelton
1
Saya tidak begitu yakin SELECT *adalah tidak-tidak untuk sebagian besar pertanyaan produksi. Jika itu meningkatkan kecepatan pengembangan Anda secara signifikan, dan membuat kode Anda jauh lebih singkat dan mudah dibaca - memungkinkan Anda untuk fokus pada hal-hal yang lebih penting - mengapa tidak SELECT *? Ini sangat tergantung pada keadaan setiap situasi dan merupakan pertukaran antara banyak faktor. Satu aturan jarang cocok untuk semuanya.
niico
2

Saya selalu menggunakan userId sebagai PK di satu tabel dan userId di tabel lain sebagai FK. sedang berpikir serius untuk menggunakan userIdPK dan userIdFK sebagai nama untuk mengidentifikasi satu sama lain. Ini akan membantu saya mengidentifikasi PK dan FK dengan cepat ketika melihat tabel dan sepertinya itu akan membersihkan kode saat menggunakan PHP / SQL untuk mengakses data sehingga lebih mudah dipahami. Terutama ketika orang lain melihat kode saya.

Ross
sumber
1

Saya menggunakan konvensi # 2. Saya bekerja dengan model data lama sekarang di mana saya tidak tahu apa singkatan dari tabel tertentu. Dimana salahnya bertele-tele?

OMG Ponies
sumber
1

Bagaimana dengan memberi nama kunci asing

role_id

di mana peran adalah peran yang dimiliki entitas yang direferensikan relatif terhadap tabel yang ada. Ini memecahkan masalah referensi rekursif dan beberapa fks ke tabel yang sama.

Dalam banyak kasus, nama tabel akan identik dengan yang direferensikan. Dalam kasus ini, ini menjadi identik dengan salah satu proposal Anda.

Bagaimanapun, memiliki argumen yang panjang adalah ide yang buruk

Jens Schauder
sumber
0

"Di mana dalam" pesanan INNER JOIN karyawan ON order.employee_id = employee.id "apakah ada kebutuhan untuk kualifikasi tambahan?".

Tidak perlu kualifikasi tambahan karena kualifikasi yang saya bicarakan sudah ada.

"Alasan pengguna bisnis merujuk ke ID Pesanan atau ID Karyawan adalah untuk memberikan konteks, tetapi pada tingkat database Anda sudah memiliki konteks karena Anda merujuk ke tabel".

Berdoa, beri tahu saya, jika kolom tersebut bernama 'ID', lalu bagaimana "merujuk [sic] ke tabel" dilakukan dengan tepat, kecuali dengan mengkualifikasikan referensi ini ke kolom ID persis seperti yang saya bicarakan?


sumber