Katakanlah saya memiliki diagram ER berikut:
Sekarang jika saya mewakili hubungan menggunakan kunci asing School
masuk Student
, saya dapat memiliki NULL
nilai (karena a Student
tidak diharuskan untuk menjadi milik a School
), misalnya:
Jadi cara yang benar (berdasarkan apa yang saya baca) adalah membuat tabel persimpangan untuk mewakili hubungan, misalnya:
Dengan cara ini, tidak ada NULL
nilai yang bisa ditampilkan dalam tabel School_has_Student
.
Tapi apa kerugian menggunakan kunci asing nullable daripada membuat tabel persimpangan?
Edit:
Saya keliru memilih ( school_id
, student_id
) menjadi kunci utama untuk School_has_Student
tabel, yang membuat hubungan banyak-ke-banyak. Kunci primer yang benar seharusnya student_id
:
Jawaban:
Kedua model mewakili hubungan yang berbeda.
Dengan menggunakan tabel gabung, Anda memodelkan hubungan banyak-ke-banyak.
Dengan menggunakan kunci asing sederhana, Anda memodelkan hubungan satu-ke-banyak.
Kerugian dari kunci asing nullable adalah tidak dapat memodelkan hubungan sebagai banyak-ke-banyak, jika itu yang ingin Anda capai.
Berdasarkan hasil edit Anda terhadap pertanyaan, Anda secara efektif membagi tabel siswa menjadi dua tabel dengan kunci yang sama. Saya biasanya melihat ini pada tabel yang memiliki terlalu banyak bidang, sehingga seseorang membaginya menjadi dua agar lebih mudah dikelola (saya menyebutnya meletakkan lipstik pada babi).
Dengan memecah tabel siswa, Anda membuat tabel kedua opsional karena catatan tidak perlu ada di tabel kedua. Yang sangat mirip dengan bidang yang tidak perlu diatur karena itu bisa nol.
Jika Anda menginginkan hubungan satu-ke-banyak, Anda jauh lebih baik menggunakan satu tabel dan membiarkan ID sekolah menjadi nol di tabel siswa. Tidak ada alasan untuk menghindari null di bidang, bahkan untuk kunci asing. Itu menandakan bahwa hubungan luar negeri adalah opsional: pengembang dan DBA memahami dengan jelas, dan mesin basis data yang mendasarinya pasti akan berfungsi dengan baik.
Jika Anda khawatir tentang bergabung, jangan khawatir. Ada semantik yang didefinisikan dengan baik untuk bagaimana bergabung bekerja dengan bidang nol. Dengan menggunakan satu tabel, Anda dapat bergabung dengan dua tabel, bukan tiga.
sumber
NULL
nilai?student_id
kunci utama dalamSchool_has_Student
tabel, yang menjaga hubungan sebagai satu-ke-banyak. Kelemahan apa yang dimiliki metode ini dibandingkan menggunakan kunci asing?Anda menulis dalam komentar di atas:
Ketika ada banyak nilai NULL di kolom kunci asing, program Anda harus berurusan dengan kolom yang sebagian besar kosong ini untuk setiap catatan yang mereka proses. Kolom mungkin akan menempati beberapa ruang disk walaupun 98% dari semua kasusnya kosong, menanyakan hubungan berarti menanyakan kolom yang memberi Anda lebih banyak lalu lintas jaringan, dan jika Anda menggunakan ORM yang menghasilkan kelas dari tabel, program Anda juga akan membutuhkan lebih banyak ruang di sisi klien daripada yang diperlukan. Menggunakan tabel persimpangan menghindari ini, hanya akan ada catatan tautan yang diperlukan di mana kunci asing yang setara tidak akan menjadi NULL.
Menentang itu, jika Anda tidak hanya memiliki beberapa nilai NULL, katakanlah 50% atau lebih hubungan bukan NULL, menggunakan tabel persimpangan memberi Anda efek sebaliknya - lebih banyak ruang disk, kompleksitas yang lebih tinggi menghasilkan lebih banyak lalu lintas jaringan dll.
Jadi menggunakan tabel persimpangan hanyalah bentuk optimasi, hanya masuk akal untuk kasus tertentu, dan terutama saat ini, di mana ruang disk dan memori menjadi lebih murah, lebih jarang dibutuhkan. Perhatikan bahwa "Dasar-dasar Sistem Basis Data" awalnya ditulis lebih dari 20 tahun yang lalu (saya menemukan referensi ke edisi kedua dari 1994), dan saya kira rekomendasi itu sudah ada di sana pada waktu itu. Sebelum 1994, optimasi ruang mungkin jauh lebih penting daripada hari ini, karena penyimpanan massal masih lebih mahal dan komputer dan jaringan jauh lebih lambat daripada hari ini.
Sebagai catatan untuk komentar pemilih: pernyataan di atas hanya mencoba mengantisipasi apa yang ada dalam pikiran penulis "Fundamentals of Database Systems" dalam rekomendasinya, saya kira dia membuat pernyataan umum yang kasar, valid untuk sebagian besar sistem. Dalam beberapa database ada optimasi lain yang mungkin seperti "kolom jarang" yang membuat penggunaan tabel persimpangan bahkan lebih usang.
Jadi jangan salah rekomendasi itu. Buku ini tidak memberitahu Anda untuk memilih tabel persimpangan untuk
{0,1}:n
hubungan secara umum, atau - seperti yang Anda tulis - bahwa ini adalah "cara yang benar". Gunakan optimasi seperti ini yang akan membuat program Anda lebih rumit hanya ketika Anda benar-benar membutuhkannya.sumber
Model konseptual akan terlihat seperti ini, yang sangat tidak lazim untuk dikatakan kurang:
Model fisik akan terlihat seperti ini, yang membingungkan untuk mengatakan lebih sedikit (orang akan berpikir itu M: M kecuali mereka melihat dari dekat):
Saran saya:
Jika Anda suka, banyak kolom (FK atau lainnya), yang tidak berlaku untuk sebagian besar siswa, pisahkan tabel menjadi tabel peran dengan rel 1: 1. Tapi itu bukan karena mereka adalah FK, itu karena kolom tidak berlaku untuk sebagian besar baris.
Kalau tidak , nullable FK adalah bagian normal dari database dan tabel join biasanya untuk rel M: M.
Penggunaan umum rel 1: 1 adalah untuk tabel peran yang memiliki kolom yang hanya berlaku jika entitas adalah tipe tertentu, dan mengekstraksi kolom BLOB untuk pertimbangan kinerja atau penyimpanan. Mengembalikan nilai null di FK bukan merupakan penggunaan umum untuk itu.
sumber
Selain jawaban lain, saya ingin menunjukkan bahwa nilai nol untuk kunci asing bersifat mendua. Apakah itu berarti:
1) Sekolah siswa (jika ada) tidak diketahui (ini adalah arti standar 'null' - nilai tidak diketahui)
2) Diketahui apakah siswa memiliki sekolah atau tidak, dan mereka tidak memilikinya
Jika Anda menggunakan arti standar nol, bagaimana Anda mewakili "siswa tidak memiliki sekolah" dalam model kunci asing Anda. Jika demikian, Anda mungkin harus membuat entri "tidak sekolah", dengan id itu sendiri di tabel sekolah. (Tidak ideal)
sumber
NULL
, itu bisa berarti: 1) Nilai tidak diketahui. 2) Nilai tidak tersedia atau ditahan. 3) Tidak atribut yang berlaku (saya pikir interpretasi ini berarti bahwa Anda dapat menentukanNULL
kunci asing).Tabel database memiliki hal yang disebut kendala ini. Jadi sangat mudah untuk membuat tabel persimpangan yang memungkinkan hanya 1 dari setiap siswa untuk muncul di tabel tetapi banyak sekolah di tabel itu. Secara efektif memberi Anda a
Teori itu bagus tetapi pada akhirnya Anda akan memodelkan basis data Anda setelah pertanyaan yang Anda ajukan.
Jika Anda ingin sering bertanya dengan pertanyaan: "siswa mana di sekolah saya", apakah Anda benar-benar ingin menanyakan seluruh tabel siswa atau memiliki tabel persimpangan yang mudah.
Dalam database: optimalkan untuk pertanyaan yang Anda ajukan.
sumber
Ada kasus penggunaan di mana menggunakan tabel ketiga sebenarnya bisa masuk akal. Contohnya mungkin murni hipotetis, tetapi saya harap ini menggambarkan poin saya dengan baik. Anggap Anda menambahkan lebih banyak kolom ke
students
tabel dan pada titik tertentu, Anda memutuskan untuk menerapkan keunikan pada catatan melalui indeks komposit pada beberapa kolom. Sangat mungkin bahwa Anda harus memasukkanschool_id
kolom juga, dan di sini hal-hal mulai menjadi berantakan. Karena cara SQL dirancang, memasukkan beberapa catatan identik manaschool_id
adalahNULL
akan mungkin. Masuk akal dari sudut pandang teknis, tetapi berlawanan dengan intuisi dan dapat menyebabkan hasil yang tidak terduga. Di sisi lain, menegakkan keunikan di atas meja persimpangan adalah mudah.Saya harus memodelkan hubungan "opsional" seperti itu baru-baru ini, di mana persyaratan untuk kendala keunikan adalah karena kolom timestamp. Meninggalkan kunci asing yang dapat dibatalkan dalam tabel tiba-tiba mengarah pada kemungkinan memasukkan catatan dengan stempel waktu yang sama (mari kita asumsikan itu adalah default, set pada catatan yang belum diaudit / setujui) - dan satu-satunya jalan keluar adalah menghapus kolom nullable.
Jadi seperti yang Anda lihat, ini adalah kasus yang cukup spesifik, dan seperti yang dicatat orang lain, biasanya Anda akan baik-baik saja dengan semua
NULL
nilainya. Itu benar-benar tergantung pada persyaratan spesifik dari model Anda.sumber
Selain banyak saran bagus yang sudah dikirimkan, secara pribadi saya bukan penggemar kunci asing kecuali mereka benar-benar diperlukan. Pertama ada hubungan M: M yang Anda referensikan. Plus, memanggil kunci asing, dan dengan demikian menarik data tabel itu ke dalam kueri Anda, memperkenalkan lebih banyak kerumitan dan tergantung pada ukuran tabel, kinerja lebih lambat. Seperti yang dikatakan orang lain, bidang FK yang tidak dapat dibatalkan dapat tidak didukung dan dapat membuat masalah integritas data.
Jika Anda mendefinisikan keadaan di mana sekolah siswa tidak diketahui atau kosong, NULL tidak akan membedakan kondisi tersebut. (Sekali lagi kita kembali ke integritas data.) Saran tabel peran oleh Tulains elegan dan memungkinkan nilai-nilai null bersih.
sumber