SQL Server: Bagaimana cara mengabaikan integritas referensial hingga COMMIT?

saya memiliki proses untuk memindahkan baris dari satu database ke database lainnya. Karena beberapa rantai referensi kunci asing melingkar saya tidak dapat menghapus baris dari database lama, juga tidak dapat memasukkannya ke dalam database baru.

Karena seluruh operasi terjadi dalam transaksi1, saya ingin SQL Server mengabaikan kegagalan integritas referensial hingga saya memanggil COMMIT TRANSACTION.

Misalnya2:

   Table: Turboencabulators         Table: Marselvanes
   =========================        =======================
PK TurboencabulatorID int    /-> PK MarselvaneID       int
^  MarselvanesID      int --/       HasGrammeter       bit
|                                   PantametricFan     varchar(50)
+-------------------------------    TurboencabulatorID int

Jika saya mencoba memasukkan turboencabulator ke dalam tabel baru, ia akan gagal tanpa marselvane sudah ada di sana. Membalikkan urutan memiliki masalah yang sama.

Saat mencoba menghapus baris lama, saya tidak dapat menghapus satu baris sampai baris lainnya dihapus.

Saya telah mencoba melakukan sistem fase n, di mana semua baris disisipkan dengan kolom apa pun yang berada di bawah batasan kunci asing yang disetel ke null. Kemudian saya memperbarui semua baris yang disisipkan, menempatkan nilai yang hilang. Lalu, untuk menghapus baris sumber, saya menghapus semua kolom yang terpengaruh oleh FK, lalu menghapus baris sebenarnya.3

Apa yang sebenarnya saya sukai adalah melakukan operasi T-SQL saya, dan meminta SQL Server tidak memberi tahu saya sampai saya mencoba memanggil komit.

Catatan

1didistribusikan
2dibuat hipotetis
3yang tidak saya lakukan lagi


person Ian Boyd    schedule 26.02.2010    source sumber
comment
Mengapa Anda memiliki referensi melingkar antara kedua tabel ini? Sepertinya itulah masalah sebenarnya.   -  person Samuel Neff    schedule 27.02.2010
comment
@Sam: setuju. Saya menduga @Ian telah menyederhanakan masalah untuk presentasi di sini, dan referensi melingkar yang sebenarnya memerlukan beberapa langkah untuk mewujudkannya. Bagaimana menurutmu, Ian?   -  person Bob Kaufman    schedule 27.02.2010
comment
@Sam, @Bob: Lihat catatan kaki 2 - jika turboencabulator dengan pelat dasar amulit prefabulasi, diapit oleh casing logaritmik yang dapat ditempa sedemikian rupa sehingga kedua bantalan pacu berada pada garis langsung dengan kipas pentametrik tidak cukup petunjuk.   -  person Ian Boyd    schedule 27.02.2010


Jawaban (2)


Anda dapat gunakan ...

ALTER TABLE whatever_table NOCHECK CONSTRAINT ALL 

untuk menghapus pemeriksaan kendala sebelum Anda mulai

dan setelah selesai hidupkan kembali dengan...

ALTER TABLE whatever_table CHECK CONSTRAINT ALL 

itulah yang akan aku lakukan.

-mengenakan

person Don Dickinson    schedule 26.02.2010
comment
Ya, itulah yang saya pikirkan. aku hanya tidak mau :( - person Ian Boyd; 27.02.2010

Bayangkan bagaimana Anda menerapkannya.

Jika hasil kunci asing akan ditunda hingga transaksi dilakukan, maka penerapan harus melakukan semua operasi pencarian/pemeriksaan/kaskade yang tidak terjadi pada waktu penyisipan/penghapusan/perbarui. Pikirkan apa arti sebenarnya dari batasan FK: rencana eksekusi penyisipan Anda akan 'diberi anotasi' dengan operasi tambahan untuk memvalidasi dan menerapkan batasan FK. Jika Anda menunda batasan tersebut, logika tambahan dalam rencana kueri harus dilepaskan dari momen eksekusi dan dimasukkan ke dalam beberapa konteks transaksi sehingga dieksekusi pada waktu penerapan. Tiba-tiba komit berubah dari operasi 'tandai transaksi yang dilakukan dalam log' singkat menjadi operasi yang melakukan semua hal yang dilewati selama transaksi sebenarnya. Bagian terburuknya adalah batasan tersebut mungkin gagal, dan pikirkan bagaimana aplikasi menangani kegagalan tersebut? Dengan penerapan batasan pada saat penyisipan dijalankan, aplikasi dapat menangkap kesalahan dan mengambil tindakan perbaikan: aplikasi mengetahui dengan tepat apa yang gagal. Tetapi jika Anda menundanya hingga dilakukan, Anda mencoba melakukan dan menangkap pengecualian, sekarang Anda perlu mencari tahu, dari pengecualian tersebut, apa yang gagal. Bayangkan betapa rumitnya kehidupan pengembang aplikasi dalam kasus tersebut.

Alasan kedua mengapa ini tidak berhasil adalah karena Anda masih belum menyelesaikan masalahnya. Anda memiliki tabel A dengan batasan FK ke B. Anda memulai transaksi, memasukkan ke B, lalu memasukkan ke A, lalu menghapus dari A, lalu menghapus dari B, lalu melakukan. Semua operasi memuaskan FK pada saat terjadinya, database memuaskan FK pada waktu komitmen. Namun jika Anda menunda pemeriksaan batasan, pemeriksaan tersebut akan gagal pada waktu penerapan!!

Jadi menurut saya integritas referensial berfungsi dengan baik sebagaimana adanya, tetapi ini dirancang untuk hierarki cascadin yang bebas dari siklus. Seperti banyak struktur data dan algoritma CS, ia rusak ketika siklus diperkenalkan. Solusi terbaik adalah menganalisis skema dan melihat apakah siklus tersebut benar-benar tidak dapat dihindari. Singkatnya, memasukkan NULL dan memperbarui penyisipan posting adalah solusi terbaik.

Sayangnya menonaktifkan batasan dan mengaktifkan kembali adalah hal yang sangat dilarang: pengaktifan kembali harus memeriksa setiap baris dalam tabel untuk memverifikasi batasan, dan akan bertahan selamanya. Jika tidak, batasan tersebut ditandai sebagai 'tidak tepercaya' dalam metadata database dan pengoptimal pada dasarnya akan mengabaikannya (akan tetap diterapkan, tetapi Anda tidak mendapatkan manfaat pengoptimalan rencana darinya).

person Remus Rusanu    schedule 26.02.2010
comment
saya mengerti, saya tidak jelas dalam contoh saya; saya dapat melihat bagaimana orang bisa salah paham. Salahku. - person Ian Boyd; 27.02.2010
comment
Saya tidak yakin saya melihat ada masalah. Asumsikan suatu transaksi memiliki kumpulan hash sederhana dari nilai kunci tabel harus ada. Tampaknya mudah untuk mempertahankannya untuk setiap penyisipan dan penghapusan alih-alih segera menerapkannya (mempertahankan hashset tampaknya tidak lebih rumit daripada penerapan saat ini). Kegagalan apa pun hanya mengembalikan seluruh transaksi, jadi tidak ada masalah tentang apa yang terjadi jika kegagalan. Tidak ada masalah dalam memasukkan lalu menghapus karena penghapusan akan menghilangkan kunci dari kumpulan hash. - person BlueMonkMN; 09.07.2018