Saat mengatur kunci asing di SQL Server, dalam keadaan apa Anda harus membuatnya jatuh pada menghapus atau memperbarui, dan apa alasan di baliknya?
Ini mungkin berlaku untuk database lain juga.
Saya terutama mencari contoh konkret dari setiap skenario, lebih disukai dari seseorang yang telah menggunakannya dengan sukses.
sql-server
database-design
foreign-keys
rdbms
cascade
Joel Coehoorn
sumber
sumber
sql-server
tag.Jawaban:
Ringkasan dari apa yang saya lihat sejauh ini:
Hapus Cascade
Pembaruan Cascade
Kapan Menggunakan Cascading
sumber
Kunci asing adalah cara terbaik untuk memastikan integritas referensial dari database. Menghindari kaskade karena menjadi sihir seperti menulis segala sesuatu dalam kumpulan karena Anda tidak percaya keajaiban di balik kompiler.
Apa yang buruk adalah penggunaan kunci asing yang salah, seperti membuatnya mundur, misalnya.
Contoh Juan Manuel adalah contoh kanonik, jika Anda menggunakan kode, ada lebih banyak peluang untuk meninggalkan DocumentItems palsu dalam database yang akan datang dan menggigit Anda.
Pembaruan berjenjang berguna, misalnya, ketika Anda memiliki referensi ke data dengan sesuatu yang dapat berubah, katakanlah kunci utama tabel pengguna adalah nama, kombinasi nama belakang. Maka Anda ingin perubahan dalam kombinasi itu menyebar ke mana pun mereka direferensikan.
@ Aidan, Kejelasan yang Anda rujuk datang dengan biaya tinggi, kesempatan meninggalkan data palsu di database Anda, yang tidak kecil . Bagi saya, biasanya hanya kurang terbiasa dengan DB dan ketidakmampuan untuk menemukan FK mana yang ada sebelum bekerja dengan DB yang menumbuhkan ketakutan itu. Entah itu, atau penyalahgunaan kaskade konstan, menggunakannya di mana entitas tidak terkait secara konseptual, atau di mana Anda harus melestarikan sejarah.
sumber
Saya tidak pernah menggunakan penghapusan cascading.
Jika saya ingin sesuatu dihapus dari database saya ingin secara eksplisit memberi tahu database apa yang ingin saya ambil.
Tentu saja mereka adalah fungsi yang tersedia dalam database dan mungkin ada saat-saat ketika tidak masalah untuk menggunakannya, misalnya jika Anda memiliki tabel 'pesanan' dan tabel 'pesananItem' Anda mungkin ingin menghapus item ketika Anda menghapus memesan.
Saya suka kejelasan yang saya dapatkan dari melakukannya dalam kode (atau prosedur tersimpan) daripada 'ajaib' terjadi.
Untuk alasan yang sama, saya juga bukan penggemar pemicu.
Yang perlu diperhatikan adalah bahwa jika Anda menghapus 'pesanan', Anda akan mendapatkan laporan '1 baris yang terpengaruh' kembali bahkan jika penghapusan bertingkat telah menghapus 50 'orderItem.
sumber
Saya banyak bekerja dengan menghapus cascading.
Senang rasanya mengetahui siapa pun yang bekerja melawan database mungkin tidak akan pernah meninggalkan data yang tidak diinginkan. Jika ketergantungan tumbuh saya hanya mengubah kendala dalam diagram di Studio Manajemen dan saya tidak perlu mengubah sp atau dataacces.
Yang mengatakan, saya punya 1 masalah dengan penghapusan cascading dan thats referensi melingkar. Ini sering mengarah ke bagian-bagian dari database yang tidak memiliki penghapusan cascading.
sumber
Saya melakukan banyak pekerjaan basis data dan jarang menemukan penghapusan kaskade bermanfaat. Satu kali saya menggunakannya secara efektif adalah dalam database pelaporan yang diperbarui oleh pekerjaan malam. Saya memastikan bahwa setiap data yang diubah diimpor dengan benar dengan menghapus semua catatan tingkat atas yang telah berubah sejak impor terakhir, kemudian mengimpor kembali catatan yang dimodifikasi dan apa pun yang berkaitan dengan mereka. Ini menyelamatkan saya dari keharusan menulis banyak penghapusan rumit yang terlihat dari bawah ke atas database saya.
Saya tidak menganggap penghapusan kaskade seburuk pemicu karena mereka hanya menghapus data, pemicu dapat memiliki semua jenis hal-hal buruk di dalamnya.
Secara umum saya menghindari Hapus nyata sama sekali dan menggunakan penghapusan logis (mis. Memiliki kolom bit bernama isDeleted yang akan disetel ke true) sebagai gantinya.
sumber
Salah satu contoh adalah ketika Anda memiliki dependensi antara entitas ... yaitu: Dokumen -> DocumentItems (ketika Anda menghapus Dokumen, DocumentItems tidak memiliki alasan untuk ada)
sumber
Gunakan penghapusan kaskade di mana Anda ingin catatan dengan FK dihapus jika catatan PK rujukannya dihapus. Dengan kata lain, di mana catatan tidak ada artinya tanpa catatan referensi.
Saya menemukan penghapusan kaskade berguna untuk memastikan bahwa referensi mati dihapus secara default daripada menyebabkan pengecualian nol.
sumber
ON Hapus Cascade:
Saat Anda ingin baris dalam tabel anak dihapus Jika baris terkait dihapus di tabel induk.
Jika pada penghapusan kaskade tidak digunakan maka kesalahan akan dinaikkan untuk integritas referensial .
ON Update Cascade:
Ketika Anda ingin perubahan kunci utama diperbarui di kunci asing
sumber
Saya telah mendengar tentang DBA dan / atau "Kebijakan Perusahaan" yang melarang penggunaan "On Delete Cascade" (dan yang lainnya) murni karena pengalaman buruk di masa lalu. Dalam satu kasus seorang pria menulis tiga pemicu yang akhirnya memanggil satu sama lain. Tiga hari untuk pulih menghasilkan larangan total pada pemicu, semua karena tindakan satu idjit.
Tentu saja kadang-kadang Pemicu diperlukan daripada "On Delete cascade", seperti ketika beberapa data anak perlu disimpan. Tetapi dalam kasus lain, sangat valid untuk menggunakan metode kasir On Delete. Keuntungan utama dari "On Delete cascade" adalah ia menangkap SEMUA anak-anak; prosedur pemicu / penyimpanan tertulis khusus mungkin tidak jika tidak dikodekan dengan benar.
Saya percaya Pengembang harus diizinkan untuk membuat keputusan berdasarkan apa pengembangan itu dan apa yang dikatakan oleh spec. Larangan karpet berdasarkan pengalaman buruk seharusnya tidak menjadi kriteria; proses berpikir "Jangan pernah gunakan" itu kejam. Panggilan penilaian perlu dilakukan setiap waktu, dan perubahan dibuat saat model bisnis berubah.
Bukankah ini yang dimaksud dengan pengembangan?
sumber
Salah satu alasan untuk menghapus kaskade (daripada melakukannya dalam kode) adalah untuk meningkatkan kinerja.
Kasus 1: Dengan penghapusan kaskade
Kasus 2: Tanpa penghapusan kaskade
Kedua, ketika Anda menambahkan tabel anak tambahan dengan penghapusan kaskade, kode dalam Kasus 1 tetap berfungsi.
Saya hanya akan menempatkan kaskade di mana semantik hubungan adalah "bagian dari". Kalau tidak, beberapa idiot akan menghapus setengah dari database Anda ketika Anda melakukannya:
sumber
Saya mencoba untuk menghindari penghapusan atau pembaruan yang saya tidak minta secara eksplisit di SQL server.
Baik melalui cascading atau melalui penggunaan pemicu. Mereka cenderung menggigit Anda di pantat beberapa saat, baik ketika mencoba melacak bug atau ketika mendiagnosis masalah kinerja.
Di mana saya akan menggunakannya dalam menjamin konsistensi untuk tidak terlalu banyak usaha. Untuk mendapatkan efek yang sama Anda harus menggunakan prosedur tersimpan.
sumber
Saya, seperti orang lain di sini, menemukan bahwa penghapusan kaskade benar-benar hanya sedikit membantu (itu benar-benar tidak banyak bekerja untuk menghapus data yang direferensikan di tabel lain - jika ada banyak tabel, Anda cukup mengotomatisasi ini dengan skrip) tetapi sangat menjengkelkan ketika seseorang secara tidak sengaja kaskade menghapus beberapa data penting yang sulit untuk dipulihkan.
Satu-satunya kasus di mana saya menggunakan adalah jika data dalam tabel tabel sangat terkontrol (misalnya, izin terbatas) dan hanya diperbarui atau dihapus dari melalui proses terkontrol (seperti pembaruan perangkat lunak) yang telah diverifikasi.
sumber
Penghapusan atau pembaruan ke S yang menghilangkan nilai kunci asing yang ditemukan di beberapa tuple R dapat ditangani dengan salah satu dari tiga cara berikut:
Propagasi disebut cascading.
Ada dua kasus:
‣ Jika sebuah tuple dalam S telah dihapus, hapus R tuple yang merujuk padanya.
‣ Jika sebuah tuple dalam S telah diperbarui, perbarui nilai dalam tuple R yang merujuk padanya.
sumber
Jika Anda bekerja pada sistem dengan banyak modul berbeda dalam versi yang berbeda, itu bisa sangat membantu, jika item kaskade yang dihapus adalah bagian dari / dimiliki oleh pemegang PK. Selain itu, semua modul akan memerlukan tambalan segera untuk membersihkan item dependen mereka sebelum menghapus pemilik PK, atau hubungan kunci asing akan dihilangkan sepenuhnya, mungkin meninggalkan banyak sampah dalam sistem jika pembersihan tidak dilakukan dengan benar.
Saya baru saja memperkenalkan penghapusan kaskade untuk tabel persimpangan baru antara dua tabel yang sudah ada (persimpangan untuk menghapus saja), setelah penghapusan kaskade telah berkecil hati untuk beberapa waktu. Ini juga tidak terlalu buruk jika data hilang.
Namun, itu adalah hal yang buruk pada tabel daftar enum-like: seseorang menghapus entri 13 - kuning dari tabel "warna", dan semua item kuning dalam database bisa dihapus. Juga, ini kadang-kadang diperbarui dengan cara delete-all-insert-all, yang mengarah ke integritas referensial yang sama sekali dihilangkan. Tentu saja itu salah, tetapi bagaimana Anda akan mengubah perangkat lunak yang kompleks yang telah berjalan selama bertahun-tahun, dengan pengenalan integritas referensial yang benar berada pada risiko efek samping yang tidak terduga?
Masalah lain adalah ketika nilai kunci asing asli harus disimpan bahkan setelah kunci primer telah dihapus. Seseorang dapat membuat kolom batu nisan dan opsi HAPUS SET NULL untuk FK asli, tetapi ini lagi membutuhkan pemicu atau kode tertentu untuk mempertahankan nilai kunci redundan (kecuali setelah penghapusan PK).
sumber
Penghapusan Cascade sangat berguna ketika mengimplementasikan entitas tipe-super dan sub-tipe logis dalam database fisik.
Ketika tabel tipe-super dan sub-tipe yang terpisah digunakan untuk secara fisik mengimplementasikan tipe-super / sub-tipe (sebagai lawan untuk menggulung semua atribut sub-tipe ke dalam tabel tipe-super fisik tunggal), ada satu-ke-satu -satu hubungan antara tabel ini dan masalah kemudian menjadi bagaimana menjaga kunci utama 100% sinkron antara tabel-tabel ini.
Penghapusan kaskade dapat menjadi alat yang sangat berguna untuk:
1) Pastikan bahwa menghapus catatan tipe-super juga menghapus catatan sub-jenis tunggal yang sesuai.
2) Pastikan bahwa setiap penghapusan catatan jenis sub juga menghapus catatan tipe super. Ini dicapai dengan menerapkan pemicu hapus "bukan-pada" pada tabel sub-tipe yang berjalan dan menghapus catatan tipe super yang sesuai, yang, pada gilirannya, kaskade menghapus catatan sub-jenis.
Menggunakan penghapusan kaskade dengan cara ini memastikan bahwa tidak ada catatan tipe atau sub-tipe anak yatim super yang pernah ada, terlepas dari apakah Anda menghapus catatan tipe super terlebih dahulu atau catatan sub-tipe terlebih dahulu.
sumber