Teknik olarak, NULL = NULL yanlıştır, bu mantıkla hiçbir NULL herhangi bir NULL'a eşittir ve tüm NULL'ler farklıdır. Bu, tüm NULL'lerin benzersiz olduğu ve benzersiz bir dizinin herhangi bir sayıda NULL'a izin vermesi gerektiği anlamına gelmez mi?
Teknik olarak, NULL = NULL yanlıştır, bu mantıkla hiçbir NULL herhangi bir NULL'a eşittir ve tüm NULL'ler farklıdır. Bu, tüm NULL'lerin benzersiz olduğu ve benzersiz bir dizinin herhangi bir sayıda NULL'a izin vermesi gerektiği anlamına gelmez mi?
Yanıtlar:
Neden bu şekilde çalışıyor? Çünkü bir zamanlar, standardın ne dediğini bilmeden veya önemsemeden bir tasarım kararı verdi (sonuçta, NULL
s ile her türlü garip davranışa sahibiz ve istediklerinde farklı davranışları zorlayabilir). Bu karar, bu durumda, dikte etti NULL = NULL
.
Çok akıllıca bir karar değildi. Yapmaları gereken, varsayılan davranışın ANSI standardına uymasıdır ve gerçekten bu tuhaf davranışı istiyorlarsa, WITH CONSIDER_NULLS_EQUAL
ya da gibi bir DDL seçeneğine izin verin WITH ALLOW_ONLY_ONE_NULL
.
Elbette, görüş açısı 20/20.
Her neyse, en temiz ya da sezgisel olmasa bile, bir çözümümüz var.
Eşsiz, filtrelenmiş bir dizin oluşturarak, uygun ANSI davranışını SQL Server 2008 ve üzeri sürümlerde alabilirsiniz.
CREATE UNIQUE INDEX foo ON dbo.bar(key) WHERE key IS NOT NULL;
Bu, birden fazla NULL
değere izin verir, çünkü bu satırlar yinelenen denetlemenin dışında bırakılır. Ek bir bonus olarak, bu, birden fazla NULL
s'ye izin verildiyse tüm tablonun oluşturduğundan daha küçük bir endeks olarak sonuçlanır (özellikle endekste tek sütun olmadığında, INCLUDE
sütunlara vb. Sahip). Bununla birlikte, filtre uygulanmış dizinlerin diğer sınırlamalarından bazılarının farkında olmak isteyebilirsiniz:
Doğru. Sql sunucusunda benzersiz bir kısıtlama veya dizinin uygulanması bir ve sadece bir NULL'a izin verir. Ayrıca, teknik olarak NULL tanımına uymadığını doğrulayın, ancak "teknik olarak" doğru olmasa da, onu daha kullanışlı hale getirmek için yaptıkları şeylerden biri. Bir PRIMARY KEY (ayrıca benzersiz bir dizin) NULL'lara izin vermez (elbette).
İlk önce - "Null value" cümlesini kullanmayı bırak, sadece seni yanıltmaya götürür. Bunun yerine, "null marker" (boş işaretçi) ifadesini kullanın - bu sütundaki gerçek değerin eksik veya uygulanamaz olduğunu belirten bir sütundaki işaretleyici kullanın (ancak, işaretleyicinin bu seçeneklerden hangisinin aslında böyle olduğunu söylemediğini not edin).
Şimdi, aşağıdakileri hayal edin (veritabanının modellenen durum hakkında tam bir bilgiye sahip olmadığı).
Situation Database
ID Code ID Code
-- ----- -- -----
1 A 1 A
2 B 2 (null)
3 C 3 C
4 B 4 (null)
Modellemekte olduğumuz bütünlük kuralı "Kod benzersiz olmalı" dır. Gerçek dünyadaki durum bunu ihlal ediyor, bu yüzden veritabanı hem 2. hem de 4. öğenin aynı anda masada olmasına izin vermiyor.
En güvenli ve en az esnek olan yaklaşım, Kod alanındaki boş işaretlere izin vermemektir, bu nedenle tutarsız veri olasılığı yoktur. En esnek yaklaşım, birden fazla boş işaretçiye izin vermek ve değerler girildiğinde benzersiz olma konusunda endişelenmek olacaktır.
Sybase programcıları, masaya yalnızca bir boş işaretçi koymaya izin veren biraz güvenli, esnek olmayan bir yaklaşıma gittiler - yorumcular bir o zamandan beri şikayet ediyorlardı. Microsoft bu davranışı sürdürdü, geriye dönük uyumluluk için sanırım.
D Codd'ün biri boş, diğeri uygulanamaz olan - iki boş işaretleyici uygulamayı düşündüğünü düşündüğüm bir yerde okudum, ancak reddetti, ancak referansı bulamıyorum. Doğru hatırlıyor muyum?
PS Null hakkında en sevdiğim alıntı: Louis Davidson, "Professional SQL Server 2000 Veri Tabanı Tasarımı", Wrox Press, 2001, sayfa 52. "Tek bir cümleye kadar kaynatıldı: NULL kötüdür."
null
bu amacı gerçekleştiremez. Çünkü eksik değer, diğer satırlardan birindeki değerle aynı olabilir.
CHECK (Value IN ('A','B','C','D'))
? Daha sonra hem SQL-Server'ın uygulaması hem de SQL standardı tablonun 5 satır olmasına izin verir (her değer için bir satır artı NULL ile 1). Ardından, tartışmalı bir şekilde, veritabanı sınırlamaları ile tutarlı olsa da, tasarımcının amacı ile tutarlı değildir. Tabloda en fazla 4 satır olması. Bir veya daha fazla satır silinmedikçe, NULL'un bir kısıtlamayı ihlal etmeyecek şekilde değiştirilebileceği bir değer yoktur.
CREATE TABLE #T(A INT NULL UNIQUE);INSERT INTO #T VALUES (1),(NULL);UPDATE #T SET A = 1 WHERE A IS NULL;
bir hataya yol açacaktır. Tasarım motivasyonlarına ilişkin teorinize göre NULL
, ilk duruma eklemeyi engellemesi gerekirdi - çünkü eksik bilgi, değerin farklı olduğuna dair hiçbir garanti olmadığı anlamına gelir.
Bu teknik olarak doğru olmayabilir, ama felsefi olarak geceleri uyumama yardımcı oluyor.
Diğer bazılarının söylediği veya söylediği gibi, NULL'yi bilinmeyen olarak düşünüyorsanız, bir NULL değerinin aslında bir NULL değerine eşit olup olmadığını belirleyemezsiniz. Bu şekilde düşünerek, NULL == NULL ifadesi, NULL olarak değerlendirmeli, yani bilinmeyen anlamına gelmelidir.
Benzersiz bir kısıtlamanın, sütun değerlerinin karşılaştırılması için kesin bir değere ihtiyacı olacaktır. Başka bir deyişle, eşitlik operatörünü kullanarak tek bir sütun değerini diğer sütun değerleriyle karşılaştırırken, geçerli olduğunu yanlış olarak değerlendirmek gerekir. Bilinmeyen, çoğu zaman sahte olarak kabul edilse de, yanlış değildir. İki NULL değer eşit olabilir veya olmayabilir ... kesin olarak belirlenemez.
Eşsiz bir kısıtlamanın, birbirinden farklı olduğu belirlenen değerleri kısıtlamak olarak düşünmesine yardımcı olur. Bununla demek istediğim şuna benzeyen bir SELECT çalıştırıyorsanız:
SELECT * from dbo.table1 WHERE ColumnWithUniqueContraint="some value"
Çoğu insan, benzersiz bir kısıtlama olduğu göz önüne alındığında bir sonuç bekler. ColumnWithUniqueConstraint öğesinde birden fazla NULL değerine izin vermişseniz, karşılaştırılmış değer olarak NULL kullanarak tablodan tek bir ayrı satır seçmek mümkün olmaz.
Buna göre, NULL tanımına göre doğru uygulanıp uygulanmadığına bakılmaksızın, çoğu durumda kesinlikle NULL değerlerine izin vermekten çok daha pratik olduğuna inanıyorum.
Bir UNIQUE
kısıtlamanın ana amaçlarından biri yinelenen kayıtları önlemektir. Bir değerin "bilinmeyen" olduğu birden fazla kaydın olabileceği bir tablonun olması gerekiyorsa, ancak aynı "bilinen" değere sahip iki kaydın bulunmasına izin verilmiyorsa, o zaman bilinmeyen değerlere daha önce yapay benzersiz tanımlayıcılar atanmalıdır. masaya eklendi.
Bir UNIQUE
kısıtlı olan ve tek bir boş değer içeren bir sütunun nadir olduğu birkaç durum vardır ; Örneğin, bir tablo sütun değerleri ve yerelleştirilmiş metin açıklamaları arasında bir eşleme içeriyorsa, bir satır için bir satır, NULL
başka bir tablodaki o sütun olduğunda görünmesi gereken tanımlamayı tanımlamayı mümkün kılar NULL
. NULL
Kullanım durumu için izin verme davranışı .
Aksi takdirde, UNIQUE
birçok özdeş kaydın varlığına izin vermek için herhangi bir sütunda kısıtlı bir veritabanı için bir temel göremiyorum , ancak anahtar değerleri ayırt edilemeyen birden fazla kayda izin verirken bunu önlemenin bir yolunu görmüyorum. Bunun NULL
kendisine eşit olmadığını beyan etmek NULL
değerleri birbirinden ayırt etmeyecektir .