Saya membaca ini tentang kata kunci SQL DEFERRABLE
dalam Sistem Database - Buku Lengkap .
Yang terakhir [TIDAK DAPAT DITERBITKAN] adalah default, dan berarti bahwa setiap kali pernyataan modifikasi database dijalankan, batasan diperiksa segera setelahnya, jika modifikasi dapat melanggar batasan kunci asing.
Namun, jika kita mendeklarasikan sebuah batasan sebagai DEFERRABLE , maka kita memiliki pilihan untuk menunggu sampai transaksi selesai sebelum memeriksa batasan tersebut.
Kami mengikuti kata kunci deferrable oleh salah AWALNYA DITANGGUHKAN atau AWALNYA SEGERA . Dalam kasus sebelumnya, pemeriksaan akan ditangguhkan sebelum setiap transaksi dilakukan. Dalam kasus terakhir, pemeriksaan akan dilakukan segera setelah setiap pernyataan.
Apa NOT DEFERRABLE
bedanya dengan DEFERRABLE INITIALLY IMMEDIATE
? Dalam kedua kasus, tampaknya, setiap kendala diperiksa setelah setiap pernyataan individu.
DEFERRABLE
menyatakan niat desainer bahwa menunda batasan adalah tindakan yang berharga atau perlu. Ini tidak terjadi untuk sebagian besar kendala database dan pelabelan semua karenaDEFERRABLE
akan kehilangan perbedaan yang berguna ini.NOT DEFERRABLE
biasanya yang tercepat.Selain jawaban (benar) lainnya, ketika berbicara tentang PostgreSQL harus dinyatakan bahwa:
dengan NOT DEFERRABLE setiap baris diperiksa pada waktu penyisipan / pembaruan
dengan DEFERRABLE (saat ini SEGERA ) semua baris diperiksa di akhir penyisipan / pembaruan
dengan deferrable (saat DITANGGUHKAN ) semua baris diperiksa pada akhir transaksi
Jadi tidak benar untuk mengatakan bahwa batasan DEFERRABLE bertindak seperti TIDAK DAPAT DITERBITKAN jika disetel ke SEGERA.
Mari kita uraikan perbedaan ini:
CREATE TABLE example( row integer NOT NULL, col integer NOT NULL, UNIQUE (row, col) DEFERRABLE INITIALLY IMMEDIATE ); INSERT INTO example (row, col) VALUES (1,1),(2,2),(3,3); UPDATE example SET row = row + 1, col = col + 1; SELECT * FROM example;
Ini dengan benar menghasilkan:
Tapi jika kita menghapus instruksi AWAL SEGERA DITERBITKAN,
ADDENDUM (12 Oktober 2017)
Perilaku ini memang didokumentasikan di sini , bagian "Kompatibilitas":
sumber
NOT DEFERRABLE
adalah kecepatan ( lihat di sini , bagian Batasan Keunikan yang Tidak Ditangguhkan , "Sadarilah bahwa ini bisa jauh lebih lambat daripada pemeriksaan keunikan langsung" ).DEFERRABLE
batasan tidak dapat dirujuk sebagai kunci asing di tabel lain ( lihat di sini , bagian Parameter , "Kolom yang direferensikan harus merupakan kolom dari batasan kunci utama atau unik yang tidak dapat ditangguhkan dalam tabel yang direferensikan" ).NOT DEFERRABLE
hanya karena kinerjanya lebih baik?NOT DEFERRABLE
2) jika setidaknya satu FK mereferensikan batasan, kami menggunakanNOT DEFERRABLE
juga 3) dalam kasus lain, kami menggunakanDEFERRABLE INITIALLY IMMEDIATE
. Ini dapat sedikit menurunkan kinerja kendala tersebut, tetapi memastikan kompatibilitas maksimum dengan DBMS lain yang kami gunakan (Oracle, SqlServer). PK dan FK tidak menjadi masalah karena kami tidak pernah memperbarui nilai mereka (yang menurut saya merupakan kebiasaan pemrograman yang baik untuk DB).Selain jelas bisa menunda, perbedaan sebenarnya adalah kinerja. Jika tidak ada penalti kinerja maka tidak perlu memiliki opsi untuk memilih dapat ditangguhkan atau tidak - semua kendala hanya akan dapat ditangguhkan.
Hukuman kinerja berkaitan dengan pengoptimalan yang dapat dilakukan database dengan pengetahuan tentang bagaimana data dibatasi. Misalnya, indeks yang dibuat untuk mendukung batasan unik di Oracle tidak dapat menjadi indeks unik jika batasan tersebut dapat ditangguhkan karena mengizinkan duplikat untuk sementara waktu. Namun, jika batasan tidak dapat ditangguhkan maka indeks bisa menjadi unik.
sumber
Saya sangat terlambat ke pesta tetapi saya ingin menambahkannya - per Desember 2018 - hanya dua database yang saya ketahui (mungkin ada lebih banyak) yang menawarkan beberapa level implementasi fitur SQL standar ini :
Database NOT DEFERRABLE DEFERRABLE DEFERRABLE INITIALLY IMMEDIATE INITIALLY DEFERRED ---------- -------------- ------------------- ------------------ Oracle N/A *1 Yes (default) Yes PostgreSQL Yes (default) Yes Yes DB2 - - - SQL Server - - - MySQL - - - MariaDB - - - SAP Sybase - - - HyperSQL - - - H2 - - - Derby - - -
* 1 Meskipun Oracle 12c menerima status
NOT DEFERRABLE
batasan , itu sebenarnya mengabaikannya dan membuatnya berfungsi sebagaiDEFERRABLE INITIALLY IMMEDIATE
.Seperti yang Anda lihat, Oracle tidak mengimplementasikan tipe pertama (
NOT DEFERRABLE
), dan itulah mengapa pengembang yang menggunakan Oracle (OP dalam kasus ini) mungkin bingung dan menganggap dua tipe pertama setara.Yang cukup menarik adalah Oracle dan PostgreSQL memiliki tipe default yang berbeda. Mungkin itu memiliki implikasi kinerja.
sumber
TIDAK DAPAT DITERBITKAN - Anda tidak dapat mengubah pemeriksaan kendala, oracle memeriksanya setelah setiap pernyataan (yaitu langsung setelah penyisipan pernyataan).
DAPAT DIUBAH SEGERA AWAL - Oracle memeriksa kendala setelah setiap pernyataan. TAPI, Anda dapat mengubahnya menjadi setelah setiap transaksi (yaitu setelah komit):
set constraint pk_tab1 deferred;
sumber