Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Pelanggaran batasan KUNCI UNIK pada INSERT WHERE COUNT(*) =0 pada SQL Server 2005

Mengapa ini tidak berhasil?

Saya percaya perilaku default SQL Server adalah melepaskan kunci bersama segera setelah tidak lagi diperlukan. Sub-kueri Anda akan menghasilkan kunci bersama (S) yang berumur pendek di tabel, yang akan dirilis segera setelah sub-kueri selesai.

Pada titik ini, tidak ada yang dapat mencegah transaksi bersamaan untuk memasukkan baris yang baru saja Anda verifikasi tidak ada.

Modifikasi apa yang perlu saya lakukan agar tidak ada kemungkinan pengecualian karena pelanggaran batasan?

Menambahkan HOLDLOCK petunjuk ke sub-kueri Anda akan menginstruksikan SQL Server untuk menahan kunci sampai transaksi selesai. (Dalam kasus Anda, ini adalah transaksi implisit.) HOLDLOCK petunjuk setara dengan SERIALIZABLE petunjuk, yang setara dengan tingkat isolasi transaksi serial yang Anda rujuk dalam daftar "pendekatan lain".

HOLDLOCK petunjuk saja sudah cukup untuk mempertahankan kunci S dan mencegah transaksi bersamaan memasukkan baris yang Anda lindungi. Namun, Anda mungkin akan menemukan kesalahan pelanggaran kunci unik Anda digantikan oleh kebuntuan, yang terjadi pada frekuensi yang sama.

Jika Anda hanya mempertahankan kunci S di atas meja, pertimbangkan perlombaan antara dua upaya bersamaan untuk menyisipkan baris yang sama, lanjutkan secara berurutan -- keduanya berhasil memperoleh kunci S di atas meja, tetapi tidak ada yang berhasil memperoleh kunci Eksklusif (X) kunci yang diperlukan untuk menjalankan penyisipan.

Untungnya ada jenis kunci lain untuk skenario yang tepat ini, yang disebut kunci Update (U). Kunci U identik dengan kunci S dengan perbedaan berikut:sementara beberapa kunci S dapat dipegang secara bersamaan pada sumber daya yang sama, hanya satu kunci U yang dapat dipegang pada satu waktu. (Dikatakan dengan cara lain, sementara kunci S kompatibel satu sama lain (yaitu dapat hidup berdampingan tanpa konflik), kunci U tidak kompatibel satu sama lain, tetapi dapat hidup berdampingan bersama kunci S; dan selanjutnya di sepanjang spektrum, kunci Eksklusif (X) tidak kompatibel dengan kunci S atau U)

Anda dapat meningkatkan kunci S implisit pada sub-kueri Anda menjadi kunci U menggunakan UPDLOCK petunjuk.

Dua upaya bersamaan untuk menyisipkan baris yang sama dalam tabel sekarang akan diserialisasi pada pernyataan pilih awal, karena ini memperoleh (dan menahan) kunci U, yang tidak kompatibel dengan kunci U lain dari upaya penyisipan bersamaan.

Nilai NULL

Masalah terpisah mungkin timbul dari fakta bahwa FieldC mengizinkan nilai NULL.

Jika ANSI_NULLS aktif (default) lalu centang kesetaraan FieldC=NULL akan mengembalikan false, bahkan dalam kasus di mana FieldC adalah NULL (Anda harus menggunakan IS NULL operator untuk memeriksa nol ketika ANSI_NULLS aktif). Karena FieldC tidak dapat dibatalkan, pemeriksaan duplikat Anda tidak akan berfungsi saat memasukkan nilai NULL.

Untuk menangani nulls dengan benar, Anda perlu memodifikasi sub-kueri EXISTS Anda untuk menggunakan IS NULL operator daripada = ketika nilai NULL sedang dimasukkan. (Atau Anda dapat mengubah tabel untuk melarang NULL di semua kolom terkait.)

Referensi Daring Buku SQL Server

  • Petunjuk Mengunci
  • Kunci Matriks Kompatibilitas
  • ANSI_NULLS


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Mendapatkan Nilai Pengembalian dari JDBC MSSQL

  2. Bagaimana mengembalikan output dari prosedur tersimpan ke dalam variabel di sql server

  3. Migrasi Cloud 101:Pindah dari SQL Server ke Azure

  4. Cari Tahu Mengapa Email Gagal Terkirim di SQL Server (T-SQL)

  5. Dapatkan Informasi Tampilan dengan Tampilan Skema Informasi VIEWS di SQL Server