SQL Server 2008 ve Üzeri
Yalnızca benzersiz bir dizine filtre uygulayın:
CREATE UNIQUE NONCLUSTERED INDEX UQ_Party_SamAccountName
ON dbo.Party(SamAccountName)
WHERE SamAccountName IS NOT NULL;
Alt Sürümlerde, Gerçekleştirilmiş Bir Görünüm Hala Gerekmez
SQL Server 2005 ve öncesi için, görünüm olmadan yapabilirsiniz. Tablolarımdan birine istediğiniz gibi benzersiz bir kısıtlama ekledim. Sütunda benzersizlik istediğim SamAccountName
, ancak birden fazla NULL'a izin vermek istediğim için, materyalize görünüm yerine materyalize bir sütun kullandım:
ALTER TABLE dbo.Party ADD SamAccountNameUnique
AS (Coalesce(SamAccountName, Convert(varchar(11), PartyID)))
ALTER TABLE dbo.Party ADD CONSTRAINT UQ_Party_SamAccountName
UNIQUE (SamAccountNameUnique)
Sadece istenen gerçek sütun NULL olduğunda, hesaplanan sütuna tüm tablo boyunca benzersiz garanti edilecek bir şey koymak zorunda. Bu durumda, PartyID
bir kimlik sütunu ve sayısal olmak hiçbiriyle eşleşmeyecek SamAccountName
, bu yüzden benim için çalıştı. Kendi yönteminizi deneyebilirsiniz; gerçek verilerinizle kesişme olasılığı olmaması için verilerinizin etki alanını anladığınızdan emin olun. Bu, bunun gibi farklılaştırıcı bir karakter eklemek kadar basit olabilir:
Coalesce('n' + SamAccountName, 'p' + Convert(varchar(11), PartyID))
PartyID
Bir gün sayısal olmasa ve bir ile çakışsa bile SamAccountName
, şimdi önemli olmayacak.
Hesaplanan sütunu içeren bir dizinin varlığının, her bir ifade sonucunun tablodaki diğer verilerle birlikte diske kaydedilmesine neden olduğunu ve bunun da ek disk alanı OLDUĞUNU unutmayın.
Bir dizin istemiyorsanız, anahtar kelimeyi PERSISTED
sütun ifadesi tanımının sonuna ekleyerek ifadenin diske önceden hesaplanmasını sağlayarak CPU'yu kaydedebilirsiniz .
SQL Server 2008 ve sonraki sürümlerde, mümkünse kesinlikle filtrelenmiş çözümü kullanın!
tartışma
Bazı veritabanı uzmanlarının bunu kesinlikle sorunları olan "vekil NULL'lar" olarak göreceğini unutmayın (çoğunlukla bir şeyin gerçek bir değer veya eksik veriler için bir vekil değer olup olmadığını belirlemeye çalışmakla ilgili sorunlar nedeniyle; sorunlar da olabilir) NULL olmayan vekil değerlerin sayısının çılgın gibi çoğalmasıyla).
Ancak, bu davanın farklı olduğuna inanıyorum. Eklediğim hesaplanmış sütun hiçbir şeyi belirlemek için asla kullanılmayacaktır. Kendisinin bir anlamı yoktur ve uygun şekilde tanımlanmış diğer sütunlarda zaten ayrı bulunmayan hiçbir bilgiyi kodlamaz. Asla seçilmemeli veya kullanılmamalıdır.
Öyleyse, benim hikayem bunun bir vekil NULL olmadığı ve buna bağlı kalıyorum! Aslında, NULL olmayan değeri, UNIQUE
NULL'ları yoksaymak için dizini kandırmaktan başka bir amaç için istemediğimizden, kullanım durumumuzda, normal vekil NULL oluşturmada ortaya çıkan sorunlardan hiçbiri yoktur.
Tüm bunlar, bunun yerine dizinli bir görünüm kullanmayla ilgili bir sorunum yok - ancak kullanım gereksinimi gibi bazı sorunlar getiriyor SCHEMABINDING
. Temel tablonuza yeni bir sütun ekleyerek eğlenin (en azından dizini bırakmanız ve ardından görünümü bırakmanız veya görünümü şemaya bağlı olmayacak şekilde değiştirmeniz gerekir). SQL Server'da (2005) (ayrıca sonraki sürümlerde), (2000) dizinli görünüm oluşturmak için gereksinimlerin tam listesine bakın .
Güncelleme
Sütununuz sayısalsa, benzersiz kısıtlamanın kullanımının Coalesce
çarpışmalara yol açmamasını sağlama zorluğu olabilir . Bu durumda, bazı seçenekler vardır. Negatif bir sayı kullanmak, "vekil NULL'ları" yalnızca negatif aralığa ve "gerçek değerleri" yalnızca pozitif aralığa koymak olabilir. Alternatif olarak, aşağıdaki desen kullanılabilir. Tabloda Issue
( IssueID
olan PRIMARY KEY
) veya orada olabilir veya olmayabilir TicketID
, ancak biri varsa, o benzersiz olmalıdır.
ALTER TABLE dbo.Issue ADD TicketUnique
AS (CASE WHEN TicketID IS NULL THEN IssueID END);
ALTER TABLE dbo.Issue ADD CONSTRAINT UQ_Issue_Ticket_AllowNull
UNIQUE (TicketID, TicketUnique);
Sorun 1 1 bilet 123 varsa, UNIQUE
kısıt değerleri (123, NULL) olacaktır. IssueID 2'de bilet yoksa açık olacaktır (NULL, 2). Bazı düşünceler, bu kısıtlamanın tablodaki herhangi bir satır için çoğaltılamayacağını ve yine de birden çok NULL'a izin vereceğini gösterecektir.