Saya memiliki situasi di mana saya perlu menerapkan batasan unik pada sekumpulan kolom, tetapi hanya untuk satu nilai kolom.
Jadi misalnya saya punya tabel seperti Tabel (ID, Nama, RecordStatus).
RecordStatus hanya dapat memiliki nilai 1 atau 2 (aktif atau dihapus), dan saya ingin membuat batasan unik pada (ID, RecordStatus) hanya ketika RecordStatus = 1, karena saya tidak peduli jika ada beberapa catatan yang dihapus dengan yang sama INDO.
Selain menulis pemicu, bisakah saya melakukan itu?
Saya menggunakan SQL Server 2005.
sql
sql-server
sql-server-2005
np-keras
sumber
sumber
Jawaban:
Tambahkan batasan cek seperti ini. Perbedaannya adalah, Anda akan mengembalikan false jika Status = 1 dan Count> 0.
http://msdn.microsoft.com/en-us/library/ms188258.aspx
sumber
Lihatlah, indeks yang difilter . Dari dokumentasi (penekanan saya):
Dan inilah contoh yang menggabungkan indeks unik dengan predikat filter:
Hal ini pada dasarnya memaksa keunikan
ID
saatRecordStatus
ini1
.Setelah indeks tersebut dibuat, pelanggaran keunikan akan menimbulkan kesalahan:
Catatan: indeks yang difilter diperkenalkan di SQL Server 2008. Untuk versi SQL Server sebelumnya, harap lihat jawaban ini .
sumber
ansi_padding
indeks yang difilter, jadi pastikan bahwa opsi ini diaktifkan dengan menjalankanSET ANSI_PADDING ON
sebelum membuat indeks yang difilter.Anda bisa memindahkan rekaman yang dihapus ke tabel yang tidak memiliki batasan, dan mungkin menggunakan tampilan dengan UNION dari dua tabel untuk mempertahankan tampilan tabel tunggal.
sumber
Anda dapat melakukan ini dengan cara yang sangat hacky ...
Buat tampilan skemabound di meja Anda.
BUAT LIHAT Apapun SELECT * FROM Table WHERE RecordStatus = 1
Sekarang buat batasan unik pada tampilan dengan bidang yang Anda inginkan.
Satu catatan tentang tampilan skemabound, jika Anda mengubah tabel yang mendasari Anda harus membuat ulang tampilan. Banyak gotcha karena itu.
sumber
Karena, Anda akan mengizinkan duplikat, batasan unik tidak akan berfungsi. Anda dapat membuat batasan pemeriksaan untuk kolom RecordStatus dan prosedur tersimpan untuk INSERT yang memeriksa catatan aktif yang ada sebelum memasukkan ID duplikat.
sumber
Jika Anda tidak dapat menggunakan NULL sebagai RecordStatus seperti yang disarankan Bill, Anda dapat menggabungkan idenya dengan indeks berbasis fungsi. Buat fungsi yang mengembalikan NULL jika RecordStatus bukan salah satu nilai yang ingin Anda pertimbangkan dalam batasan Anda (dan RecordStatus sebaliknya) dan buat indeks di atasnya.
Keuntungannya adalah Anda tidak perlu memeriksa baris lain secara eksplisit dalam tabel dalam batasan Anda, yang dapat menyebabkan masalah performa.
Saya harus mengatakan saya tidak tahu SQL server sama sekali, tetapi saya telah berhasil menggunakan pendekatan ini di Oracle.
sumber