Kunci asing merupakan bagian integral dari menciptakan hubungan dalam database relasional. Inilah alasannya, dan cara membuatnya.
Jadi kami telah menetapkan bahwa kunci utama menyediakan pengidentifikasi unik untuk tabel. Tetapi kunci utama bukan satu-satunya jenis "kunci". Basis data kami juga dapat berisi kunci asing.
Apa itu Kunci Asing?
kunci asing adalah kolom (atau kumpulan kolom) dalam satu tabel yang secara unik mengidentifikasi baris tabel lain. Ini mendefinisikan hubungan antara dua tabel.
Kunci asing memungkinkan Anda untuk referensi silang data terkait di seluruh tabel. Ini berguna ketika kolom berisi data yang direpresentasikan dalam tabel lain.
Contoh
Berikut diagram FruitShop kami database yang menunjukkan hubungan antara Buah tabel dan Unit meja.
Garis hitam yang menghubungkan dua tabel menunjukkan kunci asing. UnitId bidang pada Buah table adalah kunci asing untuk UnitId bidang pada Unit meja. Oleh karena itu, nilai yang kita masukkan ke dalam Fruit.UnitId harus sesuai dengan nilai di Units.UnitId . Ini mengaktifkan Fruit.UnitId untuk mereferensikan data di kolom lain untuk record tersebut (yaitu record yang memiliki UnitId yang sesuai ).
Data
Jadi jika Buah kami tabel berisi catatan seperti ini:
Id Buah | Nama Buah | Inventaris | UnitId | TanggalDimasukkan | Tanggal Diperbarui |
---|---|---|---|---|---|
1 | Apel | 10 | 3 | 27-11-2012 12:42:10 | 27-11-2012 12:42:10 |
Dan Unit kami tabel berisi catatan berikut:
UnitId | NamaUnit | TanggalDimasukkan | Tanggal Diperbarui |
---|---|---|---|
1 | Sepotong | 30-12-2011 12:46:15 | 30-12-2011 12:46:15 |
2 | Berkelompok | 30-12-2011 12:46:15 | 30-12-2011 12:46:15 |
3 | Kilogram | 30-12-2011 12:46:15 | 30-12-2011 12:46:15 |
4 | Wadah | 30-12-2011 12:46:15 | 30-12-2011 12:46:15 |
5 | Pound | 30-12-2011 12:46:15 | 30-12-2011 12:46:15 |
6 | Ons | 30-12-2011 12:46:15 | 30-12-2011 12:46:15 |
Anda dapat melihat bahwa
Fruit.UnitId
bidang berisi 3
. Sekarang lihat
Unit
tabel untuk record yang berisi 3
di
UnitId
bidang. Anda dapat melihat bahwa catatan ini mewakili
Kilogram
. Oleh karena itu, kita sekarang tahu bahwa apel diukur dalam kilogram.
Hal yang baik tentang pengaturan database dengan cara ini adalah, kita tidak perlu mengulang "Kilogram" untuk setiap record yang menggunakan unit tersebut. Mengurangi duplikasi adalah manfaat utama dari sistem manajemen basis data relasional.
Melihat sebanyak mungkin catatan di Buah tabel akan berbagi nama unit yang sama (misalnya, "Kilogram", "Container", "Bunch", dll), kita harus berpikir hati-hati sebelum menambahkan duplikat ke database kita. Tanpa menggunakan hubungan kunci asing, kita bisa menulis nama unit langsung ke Buah tabel (dan mungkin memanggil kolom "Unit", "UnitType" atau "UnitName"). Kemudian kita akan berakhir dengan banyak catatan yang berbagi nilai yang sama untuk kolom nama unit. Kita akan melihat "Kilogram" berulang-ulang melawan banyak rekor. Kami juga akan melihat pengulangan "Bunch", dan jenis unit populer lainnya.
Meskipun tidak selalu "salah" untuk melakukan ini, umumnya lebih efisien untuk menyimpan satu catatan untuk setiap nama unit tersebut dalam tabel terpisah, kemudian merujuk tabel tersebut melalui UnitId kolom. Melakukan hal ini lebih efisien daripada mengulangi nama unit tersebut berulang kali untuk setiap record yang dibuat di Buah meja. Ini juga memudahkan jika kita memutuskan untuk memperbarui nama unit (misalnya, ubah "Kilogram" menjadi "Kilo"). Jika kami memperbarui nama unit, itu tidak akan memengaruhi Buah tabel karena UnitId akan tetap sama. Selain itu, ini juga membantu mencegah munculnya data yang tidak konsisten di database kami.
Kendala Kunci Asing
Batasan kunci asing adalah objek database yang membantu menjaga konsistensi data kunci asing Anda. Anda membuat batasan kunci asing untuk mempertahankan integritas referensial. Dengan membuat batasan kunci asing, Anda memberi tahu MySQL untuk menerapkan aturan tertentu atas data. Saat data dimasukkan, dihapus, atau diperbarui, MySQL akan memeriksa apakah data tersebut mematuhi kunci asing yang Anda buat di antara tabel. Jika tidak, ini akan mencegah data ditulis/ditimpa/dihapus, sehingga menjaga integritas referensial.
Misalnya, jika pengguna mencoba memasukkan nilai UnitId ke dalam Fruit.UnitId kolom tetapi tidak ada catatan yang sesuai di Units.UnitId kolom, maka MySQL akan mencegah pengguna memasukkan nilai tersebut.
Saat kami membuat dua tabel, kami menambahkan batasan kunci asing ke Buah meja. Berikut kode yang kami gunakan untuk membuat batasan:
CONSTRAINT fkFruitUnits FOREIGN KEY (UnitId) REFERENCES Units (UnitId) ON DELETE RESTRICT ON UPDATE CASCADE
Saat Anda memperluas node di kiri SCHEMAS tab, Anda dapat melihat kunci asing yang kami buat (serta kunci utama):
Jika Anda mencoba memasukkan data yang tidak sesuai dengan batasan kunci asing, Anda akan mendapatkan kesalahan.
Misalnya, jika saya mencoba memasukkan catatan ke dalam Buah tabel menggunakan UnitId nilai yang tidak ada di Unit tabel, saya menerima kesalahan berikut:
Ini terjadi karena saya mencoba memasukkan nilai 5
ke dalam
UnitId
kolom ketika tidak ada nilai yang sesuai di
Units.UnitId
lapangan.
Agar ini berhasil, saya perlu memastikan ada catatan di
Unit
tabel dengan
UnitId
dari 5
.
Kunci Asing Tidak Berfungsi?
Anda mungkin menghadapi situasi sesekali di mana kunci asing tampaknya tidak berfungsi. Misalnya, Anda berhasil menyisipkan data ke dalam tabel meskipun ada kunci asing yang seharusnya mencegah data tersebut dimasukkan.
Ada beberapa hal yang dapat Anda periksa dalam situasi ini.
- Pastikan Anda telah menambahkan
ON DELETE
danON UPDATE
klausa dalam kode Anda. Misalnya,ON DELETE RESTRICT ON UPDATE CASCADE
. Lihat contoh CREATE TABLE kami untuk mengetahui kapan harus menempatkan kode ini. - Pastikan tabelnya InnoDB . Anda dapat melakukannya dengan menambahkan
ENGINE=InnoDB
ke akhirCREATE TABLE
pernyataan (lihat contoh saya dari saat kami membuat tabel kami). Beberapa mesin (seperti MyISAM ) tidak mendukung batasan kunci asing, tetapi mereka tidak memberikan peringatan apa pun tentang ini ketika Anda mencoba membuat batasan kunci asing Anda. Jika mesin default Anda bukan InnoDB maka kemungkinan kunci asing Anda tidak akan didukung. - Pastikan MySQL benar-benar memeriksa kunci asing. Anda dapat melakukannya dengan menjalankan kode berikut:
SET FOREIGN_KEY_CHECKS=1
.
Nonaktifkan Pemeriksaan Kunci Asing
Ada kalanya batasan kunci asing dapat menjadi pembatasan yang tidak perlu — sampai pada titik di mana kendala tersebut sangat menghambat upaya Anda dalam memuat data. Misalnya, ketika Anda baru saja membuat database dan Anda perlu memuat data awal. Atau jika Anda perlu menghapus banyak tabel dan memuat ulang data.
Jika Anda tidak memuat data dalam urutan yang benar, Anda mungkin akan terus mendapatkan kesalahan kunci asing karena data dimuat dalam urutan yang salah (yaitu Anda mencoba memuat tabel anak sebelum tabel induk memilikinya data dimuat).
Ini bukan hanya masalah saat memuat data. Anda juga bisa mengalami masalah ini saat membuat database di tempat pertama. Jika Anda tidak membuat tabel dalam urutan yang benar, Anda dapat mengalami kesalahan karena batasan kunci asing.
Jika Anda tidak mengetahui urutan induk-anak yang benar, mungkin diperlukan banyak waktu dan upaya untuk membuat urutan yang benar untuk membuat database atau memuat data. Dalam kasus seperti ini, Anda mungkin lebih baik memberi tahu MySQL untuk sementara waktu agar tidak memeriksa kunci asing untuk saat ini.
Anda dapat menonaktifkan pemeriksaan kunci asing dengan kode berikut:
FOREIGN_KEY_CHECKS=0
Untuk mengaktifkannya kembali, lakukan ini:
FOREIGN_KEY_CHECKS=1