Apakah saya boleh menggunakan kunci asing sebagai kunci utama?

102

Saya memiliki dua tabel:

  • Pengguna (nama pengguna, sandi)
  • Profil (profileId, gender, dateofbirth, ...)

Saat ini saya menggunakan pendekatan ini: setiap record Profil memiliki field bernama "userId" sebagai kunci asing yang terhubung ke tabel User. Ketika seorang pengguna mendaftar, catatan Profilnya secara otomatis dibuat.

Saya bingung dengan saran teman saya: untuk memiliki "userid" lapangan sebagai asing dan primary key dan menghapus "profileId" lapangan. Pendekatan mana yang lebih baik?

Duc Tran
sumber
3
Entity Framework menghasilkan itu (dengan kode terlebih dahulu) untuk relasi zeroOrOne (dan satu)-ke-satu. Jadi ... itu mungkin. Apakah ini cara terbaik ... Itu pertanyaan lain. Tapi itu valid. Saya tidak pernah melakukan itu saat membuat database saya sendiri (tapi saya bahkan tidak pernah memikirkannya).
Raphaël Althaus

Jawaban:

132

Kunci asing hampir selalu "Izinkan Duplikat", yang akan membuatnya tidak cocok sebagai Kunci Utama.

Sebagai gantinya, temukan bidang yang secara unik mengidentifikasi setiap rekaman dalam tabel, atau tambahkan bidang baru (baik bilangan bulat yang bertambah otomatis atau GUID) untuk bertindak sebagai kunci utama.

Satu-satunya pengecualian untuk ini adalah tabel dengan hubungan satu-ke-satu , di mana kunci asing dan kunci utama dari tabel tertaut adalah satu dan sama.

Robert Harvey
sumber
73
Kunci utama komposit yang terdiri dari dua kunci asing juga sangat cocok untuk mengimplementasikan hubungan banyak-ke-banyak.
kanan
1
@rezadru: Biarpun saya tidak setuju dengan hak, tetapi kunci pengganti hampir selalu merupakan pilihan yang lebih baik.
Robert Harvey
4
Tidak ada tentang kunci asing yang menentukan bahwa itu adalah 1 ke banyak (atau "izinkan duplikat" seperti yang tertulis). Batasan dan keunikan utama adalah dua konsep terpisah dalam database dan dapat dengan mudah dicampur semudah menambahkan indeks (yang akan menjadi konsep terpisah ketiga).
blindguy
40

Kunci utama selalu harus unik, kunci asing harus mengizinkan nilai non-unik jika tabel adalah hubungan satu-ke-banyak. Tidak masalah menggunakan kunci asing sebagai kunci utama jika tabel dihubungkan dengan hubungan satu-ke-satu, bukan hubungan satu-ke-banyak. Jika Anda ingin catatan pengguna yang sama memiliki kemungkinan memiliki lebih dari 1 catatan profil terkait, gunakan kunci utama terpisah, jika tidak tetap dengan apa yang Anda miliki.

kotekzot.dll
sumber
11

Ya, itu legal untuk memiliki kunci utama sebagai kunci asing. Ini adalah konstruksi langka, tetapi berlaku untuk:

  • hubungan 1: 1. Kedua tabel tidak dapat digabungkan menjadi satu karena izin dan hak istimewa yang berbeda hanya berlaku di tingkat tabel (mulai 2017, database seperti itu akan menjadi aneh).

  • hubungan 1: 0..1. Profil mungkin ada atau mungkin tidak ada, tergantung pada jenis pengguna.

  • kinerja merupakan masalah, dan desain bertindak sebagai partisi: tabel profil jarang diakses, dihosting pada disk terpisah atau memiliki kebijakan sharding yang berbeda dibandingkan dengan tabel pengguna. Tidak masuk akal jika penyimpanan yang menggarisbawahi berbentuk kolom.


sumber
Akan ada kinerja negatif jika tabel sering digabungkan, yang mengarah ke rekomendasi normal bahwa 1 tabel lebih baik. Dalam beberapa kasus, data selalu diakses secara terpisah, tidak digabungkan, dan ada manfaat organisasi memiliki dua tabel dengan hubungan 1: 1.
blindguy
4

Secara umum dianggap praktik yang buruk untuk memiliki hubungan satu dengan satu. Ini karena Anda bisa saja membuat data direpresentasikan dalam satu tabel dan mencapai hasil yang sama.

Namun, ada beberapa contoh di mana Anda mungkin tidak dapat membuat perubahan ini ke tabel yang Anda rujuk. Dalam hal ini, tidak ada masalah menggunakan kunci Asing sebagai kunci utama. Mungkin membantu untuk memiliki kunci komposit yang terdiri dari kunci primer unik yang bertambah otomatis dan kunci asing.

Saat ini saya mengerjakan sistem tempat pengguna dapat masuk dan membuat kode pendaftaran untuk digunakan dengan suatu aplikasi. Untuk alasan saya tidak akan membahas, saya tidak dapat menambahkan kolom yang diperlukan ke tabel pengguna. Jadi saya akan menelusuri rute satu ke satu dengan tabel kode.

Tshsmith
sumber
2
Saya setuju dengan Anda sebagian besar bahwa ada banyak keuntungan memiliki semua data dalam tabel yang sama sebagai kolom tambahan. Meskipun wrt ini .. "Anda hanya dapat memiliki data yang direpresentasikan dalam satu tabel dan mencapai hasil yang sama" ..: memiliki tabel terpisah dapat berguna, misalnya di sini jika entri tabel profil bersifat opsional. Misalnya, setiap nasabah bank mungkin tidak memiliki registrasi internet banking. Dalam hal ini, tabel pendaftaran IB dapat digunakan untuk membatasi tabel lain agar tidak memiliki catatan turunan lebih lanjut. Sekali lagi, ini bisa dilakukan dengan PK baru untuk tabel pendaftaran IB juga.
Teddy
1
@Teddy Demikian juga saya sangat setuju dengan apa yang Anda katakan. Namun, dalam pertanyaan awal mereka menyatakan "... catatan Profilnya secara otomatis dibuat ..." yang menyiratkan bahwa tabel Profil bukanlah opsional. Dalam situasi di mana tabel profil adalah opsional maka ya memilikinya sebagai tabel terpisah dapat dilakukan. Tapi sekali lagi, mereka hanya bisa menggunakan kolom nullable dalam tabel yang sama.
Tshith
1
Dengan menggunakan tabel kedua yang terpisah, kita dapat mencegah entri di tabel ketiga yang hanya diperbolehkan untuk orang yang memiliki entri di tabel kedua.
Teddy
Tentu saja, tetapi jika kita menggabungkan tabel 1 ke 1, kita dapat mencegah orang-orang dengan nilai null mengakses tabel ketiga (secara teknis kedua sekarang). Tetapi pertanyaan OP yang diajukan berisi baris "... saat mendaftar .. ... catatan profilnya otomatis dibuat ...", Membuat ini mubazir.
Tshsmith
Alasan utama saya untuk mempertimbangkan hal ini adalah bahwa dalam pergudangan data, merupakan praktik yang baik untuk memisahkan tabel fakta dan dimensi. Tabel fakta dan dimensi yang terpisah adalah petunjuk yang berguna saat bekerja dengan perangkat lunak seperti PowerPivot, PowerBI, dan Tableau.
Marco Rosas
4

Ya, kunci asing bisa menjadi kunci utama dalam kasus hubungan satu ke satu antara tabel tersebut

Riaj Ferdous
sumber
2
ini juga berguna untuk desain supertipe-subtipe. Kunci utama tabel subtipe harus berupa referensi kunci asing ke tabel supertipe.
axelioo
2

Saya tidak akan melakukan itu. Saya akan menyimpan profileIDsebagai kunci utama tabelProfile

Kunci asing hanyalah batasan referensial antara dua tabel

Orang dapat berargumen bahwa kunci primer diperlukan sebagai target kunci asing yang merujuknya dari tabel lain. Kunci asing adalah sekumpulan satu atau lebih kolom dalam tabel (tidak harus kunci kandidat, apalagi kunci utama, dari tabel itu) yang mungkin menyimpan nilai yang ditemukan di kolom kunci utama dari beberapa meja lainnya. Jadi kita harus memiliki kunci utama untuk mencocokkan kunci asing tersebut. Atau haruskah kita? Satu-satunya tujuan kunci utama dalam pasangan kunci utama / kunci asing adalah untuk memberikan gabungan yang tidak ambigu - untuk menjaga integritas referensial sehubungan dengan tabel "asing" yang menyimpan kunci utama yang direferensikan. Ini memastikan bahwa nilai yang dirujuk kunci asing akan selalu valid (atau null, jika diizinkan).

http://www.aisintl.com/case/primary_and_foreign_key.html

Massimiliano Peluso
sumber
1
Mungkin - jika Anda memiliki batasan FK antara User.UserID dan Profile.UserID, maka akan sangat disarankan untuk memiliki indeks di Profile.UserID. Mengapa tidak membuat indeks berkerumun utama pada Profil tabel, menyimpan indeks kedua dan banyak pekerjaan yang tidak perlu untuk mesin database?
Reversed Engineer
1

Itu tergantung bisnis dan sistemnya.

Jika userId Anda unik dan akan selalu unik, Anda dapat menggunakan userId sebagai kunci utama Anda. Tetapi jika Anda ingin memperluas sistem Anda, itu akan mempersulit. Saya menyarankan Anda untuk menambahkan kunci asing di pengguna tabel untuk membuat hubungan dengan profil tabel daripada menambahkan kunci asing di profil tabel.

Vincent Cai
sumber
0

Jawaban singkatnya: TERGANTUNG .... Dalam kasus khusus ini, mungkin baik-baik saja. Namun, para ahli akan merekomendasikan untuk tidak melakukannya setiap saat; termasuk kasus Anda.

Mengapa?

Kunci jarang unik dalam tabel ketika mereka asing (berasal dari tabel lain) ke tabel tersebut. Misalnya, ID item mungkin unik dalam tabel ITEMS, tetapi tidak dalam tabel ORDERS, karena jenis item yang sama kemungkinan besar akan ada di pesanan lain. Demikian pula, ID pesanan mungkin unik (mungkin) di tabel ORDERS, tetapi tidak di beberapa tabel lain seperti ORDER_DETAILS tempat pesanan dengan beberapa item baris dapat ada dan untuk membuat kueri terhadap item tertentu dalam pesanan tertentu, Anda memerlukan penggabungan dua FK (order_id dan item_id) sebagai PK untuk tabel ini.

Saya bukan ahli DB, tetapi jika Anda dapat membenarkan secara logis untuk memiliki nilai yang dihasilkan secara otomatis sebagai PK Anda, saya akan melakukannya. Jika ini tidak praktis, maka gabungan dua (atau mungkin lebih) FK bisa menjadi PK Anda. TAPI, saya tidak dapat memikirkan kasus di mana satu nilai FK dapat dibenarkan sebagai PK.

hfontanez.dll
sumber