Saya punya masalah ketika saya mencoba menambahkan kendala ke tabel saya. Saya mendapatkan kesalahan:
Memperkenalkan kendala KUNCI ASING 'FK74988DB24B3C886' di atas meja 'Karyawan' dapat menyebabkan siklus atau banyak jalur kaskade. Tentukan HAPUS TANPA TINDAKAN atau DIPERBARUI TANPA TINDAKAN, atau ubah batasan KUNCI ASING lainnya.
Batasan saya adalah antara Code
tabel dan employee
tabel. The Code
tabel berisi Id
, Name
, FriendlyName
, Type
dan Value
. The employee
memiliki sejumlah bidang yang kode referensi, sehingga ada dapat menjadi acuan untuk setiap jenis kode.
Saya perlu kolom diatur ke nol jika kode yang direferensikan dihapus.
Ada ide bagaimana saya bisa melakukan ini?
sql
sql-server
constraints
Ricardo Altamirano
sumber
sumber
Jawaban:
SQL Server melakukan penghitungan sederhana jalur kaskade dan, alih-alih mencoba mencari tahu apakah ada siklus yang benar-benar ada, ia mengasumsikan yang terburuk dan menolak untuk membuat tindakan referensial (CASCADE): Anda bisa dan masih harus membuat kendala tanpa tindakan referensial. Jika Anda tidak dapat mengubah desain Anda (atau melakukan hal itu akan membahayakan hal-hal) maka Anda harus mempertimbangkan menggunakan pemicu sebagai upaya terakhir.
Menyelesaikan jalur kaskade FWIW adalah masalah yang kompleks. Produk SQL lainnya hanya akan mengabaikan masalah dan memungkinkan Anda untuk membuat siklus, dalam hal ini akan menjadi perlombaan untuk melihat yang akan menimpa nilai terakhir, mungkin karena ketidaktahuan desainer (mis. ACE / Jet melakukan ini). Saya mengerti beberapa produk SQL akan berusaha menyelesaikan kasus sederhana. Faktanya tetap, SQL Server bahkan tidak mencoba, memainkannya sangat aman dengan melarang lebih dari satu jalur dan setidaknya itu memberitahu Anda begitu.
Microsoft sendiri menyarankan penggunaan pemicu bukannya kendala FK.
sumber
Situasi khas dengan beberapa jalur cascasing adalah sebagai berikut: Tabel master dengan dua detail, katakanlah "Master" dan "Detail1" dan "Detail2". Kedua detail adalah penghapusan kaskade. Sejauh ini tidak ada masalah. Tetapi bagaimana jika kedua detail memiliki hubungan satu-ke-banyak dengan beberapa tabel lain (katakanlah "SomeOtherTable"). SomeOtherTable memiliki kolom Detail1ID DAN kolom Detail2ID.
Dengan kata lain: beberapa catatan di SomeOtherTable terkait dengan Detail1-catatan dan beberapa catatan di SomeOtherTable terkait dengan catatan Detail2. Bahkan jika dijamin SomeOtherTable-records tidak pernah menjadi milik kedua Details, sekarang mustahil untuk membuat catatan SomeOhterTable menghapus semua rincian, karena ada beberapa jalur cascading dari Master ke SomeOtherTable (satu via Detail1 dan satu via Detail2). Sekarang Anda mungkin sudah memahami ini. Berikut ini adalah solusi yang mungkin:
Semua bidang ID adalah bidang kunci dan penambahan otomatis. Intinya terletak pada bidang DetailMainId dari tabel Detail. Bidang-bidang ini adalah kunci dan referensial yang bertentangan. Sekarang dimungkinkan untuk menghapus semuanya dengan hanya menghapus catatan master. Kelemahannya adalah bahwa untuk setiap detail1-record DAN untuk setiap detail2 record, harus juga ada DetailMain-record (yang sebenarnya dibuat terlebih dahulu untuk mendapatkan id yang benar dan unik).
sumber
Saya akan menunjukkan bahwa (secara fungsional) ada perbedaan BESAR antara siklus dan / atau beberapa jalur dalam SCHEMA dan DATA. Sementara siklus dan mungkin multipath dalam DATA tentu dapat mempersulit pemrosesan dan menyebabkan masalah kinerja (biaya penanganan yang "benar"), biaya karakteristik ini dalam skema harus mendekati nol.
Karena siklus yang paling jelas dalam RDB terjadi dalam struktur hierarkis (bagan org, bagian, sub bagian, dll.) Sangat disayangkan bahwa SQL Server mengasumsikan yang terburuk; yaitu, siklus skema == siklus data. Bahkan, jika Anda menggunakan batasan RI, Anda tidak dapat benar-benar membangun siklus dalam data!
Saya menduga masalah multipath serupa; yaitu, beberapa jalur dalam skema tidak selalu menyiratkan beberapa jalur dalam data, tapi saya kurang berpengalaman dengan masalah multipath.
Tentu saja jika SQL Server tidak memungkinkan siklus masih akan tunduk pada kedalaman 32, tapi itu mungkin cukup untuk sebagian besar kasus. (Sayang sekali itu bukan pengaturan database!)
Pemicu "Alih-alih Hapus" juga tidak berfungsi. Kali kedua tabel dikunjungi, pemicunya diabaikan. Jadi, jika Anda benar-benar ingin mensimulasikan kaskade Anda harus menggunakan prosedur tersimpan di hadapan siklus. Pemicu Alih-dari-Hapus akan bekerja untuk kasus multi-kasus.
Celko menyarankan cara "lebih baik" untuk mewakili hierarki yang tidak memperkenalkan siklus, tetapi ada pengorbanan.
sumber
Ada artikel yang tersedia di mana menjelaskan cara melakukan beberapa jalur penghapusan menggunakan pemicu. Mungkin ini berguna untuk skenario yang kompleks.
http://www.mssqltips.com/sqlservertip/2733/solving-the-sql-server-multiple-cascade-path-issue-with-a-trigger/
sumber
Dengan suara Anda memiliki tindakan OnDelete / OnUpdate pada salah satu Kunci Asing Anda yang ada, yang akan mengubah tabel kode Anda.
Jadi dengan membuat Kunci Asing ini, Anda akan menciptakan masalah siklik,
Misalnya Memperbarui Karyawan, menyebabkan Kode diubah oleh Tindakan Pembaruan, menyebabkan Karyawan diubah oleh Tindakan Pembaruan ... dll ...
Jika Anda memposting Definisi Tabel Anda untuk kedua tabel, & definisi Foreign Key / constraint Anda, kami harus dapat memberi tahu Anda di mana masalahnya ...
sumber
Ini karena Emplyee mungkin memiliki Koleksi entitas lain mengatakan Kualifikasi dan Kualifikasi mungkin memiliki beberapa koleksi Universitas lain misalnya
}
}
}
Pada DataContext bisa jadi seperti di bawah ini
}
dalam hal ini ada rantai dari Karyawan ke Kualifikasi dan Dari Kualifikasi ke Universitas. Jadi itu melempar pengecualian yang sama bagi saya.
Itu bekerja untuk saya ketika saya berubah
Untuk
sumber
Pemicu adalah solusi untuk masalah ini:
sumber
Ini adalah kesalahan kebijakan pemicu basis data jenis. Pemicu adalah kode dan dapat menambahkan beberapa kecerdasan atau kondisi ke relasi Cascade seperti Penghapusan Cascade. Anda mungkin perlu mengkhususkan opsi tabel terkait di sekitar ini seperti Mematikan CascadeOnDelete :
Atau Matikan fitur ini sepenuhnya:
sumber
Solusi saya untuk masalah ini yang dihadapi menggunakan ASP.NET Core 2.0 dan EF Core 2.0 adalah dengan melakukan hal berikut secara berurutan:
Jalankan
update-database
perintah di Package Management Console (PMC) untuk membuat database (ini menghasilkan "Memperkenalkan kendala KUNCI ASING ... dapat menyebabkan siklus atau beberapa jalur kaskade.")Jalankan
script-migration -Idempotent
perintah di PMC untuk membuat skrip yang dapat dijalankan terlepas dari tabel / batasan yang adaAmbil skrip yang dihasilkan dan temukan
ON DELETE CASCADE
serta ganti denganON DELETE NO ACTION
Jalankan SQL yang dimodifikasi terhadap database
Sekarang, migrasi Anda harus mutakhir dan penghapusan berjenjang tidak boleh terjadi.
Sayang sekali saya tidak dapat menemukan cara untuk melakukan ini di Entity Framework Core 2.0.
Semoga berhasil!
sumber