Saya memiliki tabel yang saat ini memiliki nilai duplikat di kolom.
Saya tidak dapat menghapus duplikat yang salah ini tetapi saya ingin mencegah nilai-nilai non-unik tambahan ditambahkan.
Bisakah saya membuat UNIQUE
yang tidak memeriksa kepatuhan yang ada?
Saya sudah mencoba menggunakan NOCHECK
tetapi tidak berhasil.
Dalam hal ini saya memiliki tabel yang mengaitkan informasi perizinan dengan "Nama Perusahaan"
EDIT: Memiliki beberapa baris dengan "CompanyName" yang sama adalah data yang buruk, tetapi kami tidak dapat menghapus atau memperbarui duplikat tersebut saat ini. Salah satu pendekatan adalah untuk memiliki INSERT
penggunaan prosedur tersimpan yang akan gagal untuk duplikat ... Jika mungkin memiliki SQL memeriksa keunikan sendiri, itu akan lebih baik.
Data ini dipertanyakan dengan nama perusahaan. Untuk beberapa duplikat yang ada, ini berarti bahwa beberapa baris dikembalikan dan ditampilkan ... Meskipun ini salah, ini dapat diterima dalam kasus penggunaan kami. Tujuannya adalah untuk mencegahnya di masa depan. Sepertinya saya dari komentar bahwa saya harus melakukan logika ini dalam prosedur yang tersimpan.
Jawaban:
Jawabannya iya". Anda dapat melakukan ini dengan indeks yang difilter (lihat di sini untuk dokumentasi).
Misalnya, Anda dapat melakukan:
Ini menciptakan indeks unik, hanya pada baris baru , bukan pada baris lama. Formulasi khusus ini akan memungkinkan duplikat dengan nilai yang ada.
Jika Anda hanya memiliki beberapa duplikat, Anda dapat melakukan sesuatu seperti:
sumber
Ya, Anda bisa melakukannya.
Ini adalah tabel dengan duplikat:
Mari kita abaikan yang sudah ada, dan pastikan tidak ada duplikat baru yang dapat ditambahkan:
Mari kita coba solusi ini:
sumber
UNIQUE
kendala dalam kolom nullable memastikan bahwa paling banyakNULL
nilai tunggal . Standar SQL (dan hampir semua DBMS SQL lainnya) mengatakan bahwa ia harus mengizinkan sejumlahNULL
nilai (yaitu batasannya harus mengabaikan nilai nol).Indeks unik yang difilter adalah ide yang brilian tetapi memiliki sedikit kerugian - tidak peduli apakah Anda menggunakan
WHERE identity_column > <current value>
kondisi atauWHERE identity_column NOT IN (<list of ids for duplicate values here>)
.Dengan pendekatan pertama, Anda masih dapat memasukkan data duplikat di masa depan, duplikat data yang ada (sekarang). Misalnya, jika Anda memiliki (bahkan hanya satu) baris sekarang
CompanyName = 'Software Inc.'
, indeks tidak akan melarang penyisipan satu baris lagi dengan nama perusahaan yang sama. Itu hanya akan melarangnya jika Anda mencoba dua kali.Dengan pendekatan kedua ada peningkatan, hal di atas tidak akan bekerja (yang baik.) Namun, Anda masih dapat memasukkan lebih banyak duplikat atau duplikat yang ada. Misalnya, jika Anda memiliki (dua atau lebih) baris dengan sekarang
CompanyName = 'DoubleData Co.'
, indeks tidak akan melarang penyisipan satu baris lagi dengan nama perusahaan yang sama. Itu hanya akan melarangnya jika Anda mencoba dua kali.(Pembaruan) Ini dapat diperbaiki jika untuk setiap nama duplikat, Anda tetap keluar dari daftar pengecualian satu id. Jika, seperti contoh di atas, ada 4 baris dengan duplikat
CompanyName = DoubleData Co.
dan ID4,6,8,9
, daftar pengecualian harus hanya memiliki 3 ID ini.Dengan pendekatan kedua kelemahan lain adalah kondisi rumit (berapa rumit tergantung pada berapa banyak duplikat ada di tempat pertama), karena SQL-Server tampaknya tidak mendukung
NOT IN
operator diWHERE
bagian indeks yang difilter. Lihat SQL-Fiddle . Alih-alihWHERE (CompanyID NOT IN (3,7,4,6,8,9))
, Anda harus memiliki sesuatu sepertiWHERE (CompanyID <> 3 AND CompanyID <> 7 AND CompanyID <> 4 AND CompanyID <> 6 AND CompanyID <> 8 AND CompanyID <> 9)
saya tidak yakin apakah ada implikasi efisiensi dengan kondisi seperti itu, jika Anda memiliki ratusan nama rangkap.Solusi lain (mirip dengan @Alex Kuznetsov) adalah menambahkan kolom lain, mengisinya dengan nomor peringkat dan menambahkan indeks unik termasuk kolom ini:
Kemudian, memasukkan baris dengan nama duplikat akan gagal karena
DEFAULT 1
properti dan indeks unik. Ini masih tidak 100% sangat mudah (sementara Alex adalah). Duplikat akan tetap masuk jikaRn
secara eksplisit diatur dalamINSERT
pernyataan atau jikaRn
nilainya diperbarui secara jahat.SQL-Fiddle-2
sumber
Alternatif lain adalah menulis fungsi skalar yang memeriksa apakah suatu nilai sudah ada dalam tabel dan kemudian memanggil fungsi itu dari batasan cek.
Ini akan melakukan hal-hal mengerikan untuk kinerja.
sumber
Saya mencari yang sama - buat indeks unik yang tidak bisa dipercaya sehingga data buruk yang ada diabaikan, tetapi catatan baru tidak dapat duplikat dari apa pun yang sudah ada.
Saat membaca utas ini, saya sadar bahwa solusi yang lebih baik adalah menulis pemicu yang akan memeriksa [dimasukkan] pada tabel induk untuk duplikat, dan jika ada duplikat di antara tabel tersebut, ROLLBACK TRAN.
sumber