SQL sunucusunda neden NULL = NULL yanlış olarak değerlendirilir?


151

SQL sunucusunda nullParam=NULLbir where cümlesine sahipseniz , her zaman false olarak değerlendirilir. Bu mantığa aykırı ve bana birçok hataya neden oldu. Anlıyorum IS NULLve IS NOT NULLanahtar kelimeler bunu yapmak için doğru bir yoldur. Peki SQL sunucusu neden bu şekilde davranıyor?


170
Benim kız kardeşim yok, arkadaşım da yok. "NULL = NULL" ise ortak bir kız kardeşimiz var ve bu nedenle akrabayız! :)
Matt Hamilton

11
SQL NULL'lerinde uzun süredir devam eden bir tartışma var (örneğin bkz: en.wikipedia.org/wiki/Null_%28SQL%29#Controversy ve firstsql.com/inulls.htm ). Buradaki özel nokta, eşitliğin uzun süredir yerleşik bir matematiksel kavram olmasıdır ve SQL onu ihlal eder - eşitlik dönüşlüdür: her x için, x = x. Bu her zaman doğru olmalıdır, aksi takdirde standart olmayan bir eşitlik yorumuna giriş yapılır ve sonuç kafa karışıklığıdır.
MaD70

14
Matematiği hiç ihlal etmiyor. İki sayı düşünüyorum. Size ne olduklarını söylemeyeceğim. Şimdi bana söyle, onlar eşit mi?
Tom H

10
@Matt, benzetmenize katılmıyorum. NULL = NULL, ortak bir kız kardeşiniz olduğu anlamına gelmez, ikinizin de kız kardeşi olmadığı anlamına gelir.
reustmd

5
@ manu08 Hayır, mevcut uygulama (NULL hiçbir zaman NULL'a eşit değildir) ikimizin de bir kız kardeşi olmadığı anlamına gelir, bu da benim açımdan buydu.
Matt Hamilton

Yanıtlar:


211

Bu durumda boş değeri "bilinmeyen" olarak düşünün (veya "yok"). Her iki durumda da eşit olduklarını söyleyemezsiniz çünkü ikisinin de değerini bilmiyorsunuz. Dolayısıyla, null = null doğru değil (sisteminize bağlı olarak yanlış veya null) olarak değerlendirilir, çünkü bunların eşit olduğunu söyleyecek değerleri bilmiyorsunuz. Bu davranış ANSI SQL-92 standardında tanımlanmıştır.

DÜZENLEME: Bu, ansi_nulls ayarınıza bağlıdır . ANSI_NULLS kapalıysa, bu doğru olarak DEĞERLENDİRİLECEKTİR. Bir örnek için aşağıdaki kodu çalıştırın ...

set ansi_nulls off

if null = null
    print 'true'
else
    print 'false'


set ansi_nulls ON

if null = null
    print 'true'
else
    print 'false'

11
x = x yalnızca x bilinen bir değer olduğunda doğru olur . NULL, bilinmeyen bir değerin metinsel bir temsilidir . İki bilinmeyen değeriniz varsa, eşitlikleri hakkında kesin olarak hiçbir şey söyleyemezsiniz. Bunun birkaç yüzyıldır da geçerli olduğuna inanıyorum.
Dewayne Christensen

4
Aralık olduğu için mevsimlik bir örnek verelim. Ağacın altında iki hediyem var. Şimdi bana aynı şeyden iki tane alıp almadığımı söyle.
Dewayne Christensen

5
SQL NULL, sizin de sahip olduğunuz IEEE kayan noktalı NaN'den farklı değildir (NaN == NaN) == false && (NaN != Nan) == false && (NaN < NaN) == false && ...- çünkü, eğer bu bir sayı değilse, onun hakkında fazla bir şey söyleyemezsiniz; bilinmeyen bir şey. Konsept, daha önce hiç görmemiş insanlar için sezgisel olmasa bile sağlamdır.
Pavel Minaev

8
Burada refleksivite ihlali yoktur çünkü NULL, değerler kümesinin bir üyesi değildir (ilişkisel terimlerle etki alanı). NULL bir değer değildir . Bilinmeyen değer için bir yer tutucudur.
Pavel Minaev

9
Başka bir deyişle, NULLbir SQL ifadesindeki her biri ayrı bir matematiksel değişken olarak ele alınabilir . Dolayısıyla bir ifade , nerede ve bağlı olmayan değişkenler NULL = NULLolarak ele alınmalıdır . Şimdi birisi size sorarsa, değeri nedir? Tek mantıklı cevap "bazıları " dır . Yani - ya da onu SQL'e geri dönüştürüyoruz . x = yxyx = yz(x = y) = z(NULL = NULL) = NULL
Pavel Minaev

131

Frank kaç yaşında? Bilmiyorum (boş).

Shirley kaç yaşında? Bilmiyorum (boş).

Frank ve Shirley aynı yaşta mı?

Doğru cevap "Bilmiyorum" (boş) olmalı, "hayır" değil, çünkü Frank ve Shirley aynı yaşta olabilir , biz bilmiyoruz.


4
Boş değerin "bilinmeyen" anlamına geldiğine katılmıyorum. Gerçekte anlamı "veri yok". Bu, bilginin bilinmediği durumu temsil etmek için kullanılabilir, ancak aslında bir şeyin var olmadığını belirtmek için kullanılması daha olasıdır. Örneğinize devam edersek: Frank'in ikinci adı nedir? Bir (boş) yok. Shirley'in göbek adı nedir? Bir tane yok (boş). Frank ve Shirley aynı göbek ismine mi sahip? Evet? Hayır? Bilmiyor musunuz? "Hayır" için bir argüman görebiliyorum ve "bilmiyorum" için bir argüman görebiliyorum, ancak aşırı derecede gerçek olmadığınız sürece "evet" için gerçek bir argüman yok.
Richiban

2
@richiban Katılmıyorum. Bir satırın olmaması 'veri yok' anlamına gelir
Neil McGuigan

1
@NeilMcGuigan Kendi tablosu olan veriler için bu doğrudur, peki ya bir sütunda temsil edilen veriler? Verilerin var olmadığı gerçeğini temsil etmek için "boş" kullanmaz mısınız? 'Bilinmiyor', verilerin eksik olmasının çok özel bir nedenidir.
Richiban

3
Ama null = nullverim FALSEdeğil NULL.
slartidan

1
@slartidan Size katılıyorum, ancak bu yanlış
Neil McGuigan

29

Burada umarım konumumu netleştireceğim.

Bu NULL = NULLdeğerlendirme FALSEyanlıştır. Hacker ve Mister doğru cevap verdi NULL. İşte nedeni. Dewayne Christensen, Scott Ivey'e bir yorumda bana şunları yazdı :

Aralık olduğu için mevsimlik bir örnek verelim. Ağacın altında iki hediyem var. Şimdi bana aynı şeyden iki tane alıp almadığımı söyle.

Farklı olabilirler veya eşit olabilirler, her iki hediyeyi de açana kadar bilemezsiniz . Kim bilir? Birbirini tanımayan ve her ikisi de size aynı hediyeyi vermiş olan iki kişiyi davet ettiniz - nadir ama imkansız değil § .

Öyleyse soru: bu iki UNKNOWN sunum aynı mı (eşit, =)? Doğru cevap: BİLİNMİYOR (yani NULL).

Bu örnek, ".. ( falseveya nullsisteminize bağlı olarak) .." nin doğru bir cevap olduğunu göstermeyi amaçladı - bu değil, sadece NULL 3VL'de doğru (veya yanlış cevaplar veren bir sistemi kabul etmeniz uygun mu? )

Bu soruya verilecek doğru cevap şu iki noktayı vurgulamalıdır:

  • üç değerli mantık (3VL) mantığa aykırıdır (emin olmak için Stackoverflow'da ve diğer forumlarda bu konuyla ilgili sayısız diğer soruya bakın);
  • SQL tabanlı DBMS'ler genellikle 3VL'ye bile saygı göstermezler, bazen yanlış yanıtlar verirler (orijinal posterin iddia ettiği gibi, bu durumda SQL Server yapar).

Bu yüzden yineliyorum: SQL, eşitliğin refleksif özelliğini yorumlamaya zorlamak için iyi değildir, ki bu şunu ifade eder:

for any x, x = x §§ (sade İngilizce'de: söylemin evreni ne olursa olsun, bir "şey" her zaman kendisine eşittir ).

.. bir 3il içinde ( TRUE, FALSE, NULL). İnsanların beklenti 2il (uyumlaştıracağını TRUE, FALSEhatta SQL diğer tüm değerleri için geçerli olduğu), yani x = x her zaman için değerlendirmek TRUE istisnasız - x'in olası değeri için,.

Ayrıca NULL'ların, ilişki değişkenlerinin bir parçası olarak öznitelik değerleri (??) olarak atayabilecekleri geçerli "değer olmayanlar " (savunucuları gibi) olduğuna dikkat edin. Dolayısıyla, bunlar yalnızca mantıksal ifadelerin türü için değil, her türden (etki alanı) kabul edilebilir değerlerdir.

Demek istediğim şuydu : NULLdeğer olarak "tuhaf bir canavar". Örtüşme olmadan şunu söylemeyi tercih ederim: saçma .

Bu formülasyonun çok daha net ve daha az tartışmalı olduğunu düşünüyorum - yetersiz İngilizce yeterliliğim için üzgünüm.

Bu, NULL'lerin sorunlarından yalnızca biridir . Mümkünse onlardan tamamen kaçınmak daha iyidir.

§ Burada değerlerle ilgileniyoruz , bu nedenle iki hediyenin her zaman iki farklı fiziksel nesne olması, geçerli bir itiraz değildir; Eğer ikna olmadıysanız özür dilerim, burası değer ve "nesne" semantiği arasındaki farkı açıklayacak yer değildir (İlişkisel Cebir başlangıçtan itibaren değer anlamsallığına sahiptir - Codd'un bilgi ilkesine bakın; bazı SQL DBMS uygulamacılarının Ortak bir anlam bile umursamıyorum).

§§ , bildiğim kadarıyla, bu, antik çağlardan beri kabul edilen bir aksiyomdur (bir şekilde veya başka bir şekilde, ancak her zaman 2VL'de yorumlanır) ve tam olarak çünkü çok sezgiseldir. 3VL'ler (gerçekte bir mantık ailesidir) çok daha yeni bir gelişmedir (ancak ilk ne zaman geliştirildiğinden emin değilim).

Yan not: Eğer birisi SQL NULL'ları gerekçelendirmek için Alt , Birim ve Seçenek Türlerini tanıtacaksa , ancak NULL'larla SQL uygulamalarının nasıl sağlam bir sisteme sahip olduğunu gösteren oldukça ayrıntılı bir incelemeden sonra ikna olacağım ve sonunda, NULL'ların (bu "tam olmayan değerler") gerçekte ne olduğu.


Aşağıda bazı yazarlardan alıntı yapacağım. Herhangi bir hata ya da eksiklik muhtemelen benimdir ve orijinal yazarlara ait değildir.

Joe Celko SQL NULL'larda

Joe Celko'nun bu forumda sık sık alıntı yaptığını görüyorum. Görünüşe göre burada çok saygın bir yazar. Ben de kendi kendime dedim ki: "SQL NULL'lar hakkında ne yazdı? NULL'ların sayısız problemini nasıl açıklıyor?". Bir arkadaşımın akıllılar için Joe Celko'nun SQL'sinin bir e-kitap sürümü var: gelişmiş SQL programlama, 3. sürüm . Bakalım.

İlk olarak, içindekiler tablosu. Beni en çok etkileyen şey, NULL'dan kaç kez bahsedildiği ve çok çeşitli bağlamlarda:

3.4 Aritmetik ve NULL'lar 109
3.5 NULL'a ve NULL'dan Değerleri Dönüştürme 110
3.5.1 NULLIF () Fonksiyonu 110
6 NULL'lar: SQL'de Eksik Veriler 185
6.4 NULL'ları Karşılaştırma 190
6.5
NULL'lar ve Mantık 190 6.5.1 Alt Sorgu Öngörülerinde NULLS 191
6.5.2 Standart SQL Çözümleri 193
6.6 Matematik ve NULL'lar 193
6.7 Fonksiyonlar ve NULL'lar 193
6.8 NULL'lar ve Konak Dilleri 194
6.9 NULL'lar için Tasarım Önerileri 195
6.9.1 Ana Bilgisayar Programlarından NULL'lerden Kaçınma 197
6.10 Birden Fazla NULL Değerine İlişkin Bir Not 198
10.1 IS NULL Predicate 241
10.1. 1 NULL Kaynakları 242
...

ve bunun gibi. Bana "iğrenç özel durum" gibi geliyor.

Telif hakkı nedeniyle kendimi temel konularla sınırlamaya çalışarak, bu kitaptan alıntılarla bu davalardan bazılarına gideceğim. Bence bu alıntılar "adil kullanım" doktrini kapsamına giriyor ve kitabı satın almaya teşvik bile edebiliyorlar - bu yüzden hiç kimsenin şikayet etmemesini umuyorum (aksi takdirde hepsini olmasa da çoğunu silmem gerekecek). Ayrıca, aynı nedenle kod parçacıklarını bildirmekten de kaçınmalıyım. Bunun için üzgünüm. Ayrıntılı muhakeme hakkında okumak için kitabı satın alın.

Aşağıda, parantez içindeki sayfa numaraları.

BOŞ DEĞİL Kısıtlaması (11)

En önemli sütun kısıtlaması, bir sütunda NULL kullanımını yasaklayan NOT NULL'dur. Bu kısıtlamayı rutin olarak kullanın ve yalnızca iyi bir nedeniniz olduğunda kaldırın. Verilerle ilgili sorgulamalar yaptığınızda NULL değerlerin komplikasyonlarından kaçınmanıza yardımcı olacaktır .

Bu bir değer değil ; bir değerin gidebileceği bir yeri tutan bir işarettir.

Yine bu "değer ama tam anlamıyla bir değer değil" saçmalığı. Gerisi bana oldukça mantıklı geliyor.

(12)

Kısacası, NULL'lar SQL'de daha sonra tartışacağımız birçok düzensiz özelliğe neden olur. En iyi bahsiniz, kaçınamadığınız durumlarda NULL'ların durumlarını ve kurallarını ezberlemektir.

SQL, NULLs ve infinite eğilimleri:

(104) BÖLÜM 3: SQL'DE SAYISAL VERİ

SQL, matematik için IEEE modelini çeşitli nedenlerle kabul etmemiştir.

...

SQL'de matematik için IEEE kurallarına izin verilseydi, sonsuz için tür dönüştürme kurallarına ve dönüşümden sonra sonsuz bir tam sayısal değeri temsil etmenin bir yoluna ihtiyacımız olacaktı. İnsanların NULL'larla yeterince sorunu var, o yüzden oraya gitmeyelim.

SQL uygulamaları, belirli bağlamlarda NULL'un gerçekte ne anlama geldiğine karar vermedi:

3.6.2 Üstel Fonksiyonlar (116)

Sorun, logaritmaların tanımsız olmasıdır (x <= 0). Bazı SQL uygulamaları bir hata mesajı verirken bazıları NULL ve DB2 / 400 döndürür ; sürüm 3 sürüm 1, sonuç olarak * NEGINF ("negatif sonsuzluk" un kısaltması) döndürdü.

Joe Celko, David McGoveran ve CJ Date'den alıntı yapıyor:

6 NULL: SQL'de Eksik Veri (185)

Onların kitabında Sybase ve SQL Server Bir Kılavuz , David McGoveran ve CJ tarihi şunları söyledi: “Şu anda tanımlanmış ve SQL uygulandığı şekliyle En az, boş değerlere daha bu yazarın görüşü, değer oldukları ve kaçınılmalıdır çok daha sorunludur; çok garip ve tutarsız davranışlar sergilerler ve zengin bir hata ve kafa karışıklığı kaynağı olabilirler. (Lütfen bu yorumların ve eleştirilerin yalnızca SQL Server için değil, SQL tarzı NULL'leri destekleyen tüm sistemler için geçerli olduğunu unutmayın.) "

Uyuşturucu bağımlılığı olarak NULL'lar :

(186/187)

Bu kitabın geri kalanında, çelişkili görünebilir, ancak değildir onları kullanmamanızı tavsiye edeceğim . NULL'u bir ilaç olarak düşünün; doğru kullanın ve sizin için işe yarar, ancak kötüye kullanırsanız her şeyi mahvedebilir. En iyi politikanız, mümkün olduğunda BOŞ'lardan kaçınmak ve gerektiğinde bunları doğru şekilde kullanmaktır.

Buradaki tek itirazım, belirli uygulama davranışlarıyla kötü bir şekilde etkileşime giren "bunları doğru şekilde kullanmaktır".

6.5.1 Alt Sorgu Tahminlerinde NULLS (191/192)

İnsanlar, bir alt sorgunun genellikle NULL ile karşılaştırmayı gizlediğini unutur. Şu iki tabloyu düşünün:

...

Sonuç boş olacaktır. Bu mantık dışıdır , ancak doğrudur.

(ayırıcı)

6.5.2 Standart SQL Çözümleri (193)

SQL-92, formun yeni bir yüklemini ekleyerek bazı 3VL (üç değerli mantık) problemlerini çözdü:

<arama koşulu> [DEĞİL] DOĞRU | YANLIŞ | BİLİNMEYEN

Ancak UNKNOWN kendi başına bir sorun kaynağıdır, bu nedenle CJ Date, aşağıda alıntılanan kitabında bölüm 4.5'te öneriyor . SQL'de Boş Değerlerden Kaçınma :

  • UNKNOWN anahtar kelimesini hiçbir bağlamda kullanmayın.

Aşağıda bağlantısı verilen UNKNOWN'daki "ASIDE" bölümünü okuyun .

6.8 NULL'lar ve Konak Dilleri (194)

Ancak, bir ana bilgisayar programına geçirilmeleri gerektiğinde NULL'ların nasıl işlendiğini bilmelisiniz. Gömme işleminin tanımlandığı hiçbir standart ana bilgisayar dili NULL'leri desteklemez, bu da onları veritabanı şemanızda kullanmaktan kaçınmanız için başka bir iyi nedendir.

(ayırıcı)

6.9 NULL'lar için Tasarım Önerileri (195)

Mümkün olduğunda tüm temel tablolarınızı tüm sütunlarda NOT NULL kısıtlamaları ile bildirmek iyi bir fikirdir. NULL'lar SQL bilmeyenlerin kafasını karıştırır ve NULL'lar pahalıdır.

İtiraz: NULL'lar SQL'i iyi bilen kişilerin bile kafasını karıştırır, aşağıya bakınız.

(195)

YABANCI ANAHTARlarda BOŞ'lardan kaçınılmalıdır. SQL, bu "şüphenin faydası" ilişkisine izin verir, ancak birleştirmeleri içeren sorgularda bilgi kaybına neden olabilir. Örneğin, Envanterde bir Siparişler tablosu tarafından YABANCI ANAHTAR olarak atıfta bulunulan bir parça numarası kodu verildiğinde, BOŞ olan parçaların bir listesini almakta sorun yaşarsınız. Bu zorunlu bir ilişkidir; olmayan bir parçayı sipariş edemezsiniz.

(ayırıcı)

6.9.1 Ana Bilgisayar Programlarından NULL'lardan Kaçınma (197)

Bazı programlama disiplinleri ile Ana Bilgisayar Programlarından veritabanına NULL koymayı önleyebilirsiniz.

...

  1. Eksik verilerin programlama ve raporlama üzerindeki etkisini belirleme: NULL içeren sayısal sütunlar bir sorundur, çünkü toplama işlevlerini kullanan sorgular yanıltıcı sonuçlar sağlayabilir.

(ayırıcı)

(227)

Boş bir kümenin TOPLA () değeri her zaman NULL olur. Bu numarayı kullanırken yapılan en yaygın programlama hatalarından biri, birden fazla satır döndürebilen bir sorgu yazmaktır. Düşünmediyseniz, son örneği şu şekilde yazmış olabilirsiniz: ...

(ayırıcı)

10.1.1 NULL Kaynakları (242)

NULL'ların nerede oluşabileceğini hatırlamak önemlidir. Bir sütundaki olası bir değerden daha fazlasıdırlar . Boş kümelerdeki toplama işlevleri, OUTER JOIN'ler, NULL'larla aritmetik ifadeler ve OLAP operatörlerinin tümü NULL döndürür. Bu yapılar genellikle GÖRÜNÜM'lerde sütun olarak görünür.

(ayırıcı)

(301)

NULL'larla ilgili başka bir sorun, IN tahminlerini EXISTS tahminlerine dönüştürmeye çalıştığınızda bulunur.

(ayırıcı)

16.3 TÜM Tahmin ve Ekstrema İşlevleri (313)

İlk bakışta bu iki yüklemin SQL'de aynı olmaması mantığa aykırıdır:

...

Ancak ekstremma işlevlerinin kurallarını hatırlamanız gerekir - daha büyük veya en küçük değerleri döndürmeden önce tüm NULL'leri çıkarırlar. ALL koşulu, NULL'leri düşürmez, böylece onları sonuçlarda elde edebilirsiniz.

(ayırıcı)

(315)

Bununla birlikte, standarttaki tanım olumsuz olarak ifade edilmiştir, böylece BOŞLAR şüpheden faydalanır. ...

Gördüğünüz gibi, UNIQUE kısıtlamalarda NULL'lardan kaçınmak iyi bir fikirdir.

GROUP BY tartışılıyor:

NULL'lar birbirlerine eşitmiş gibi davranılır ve kendi gruplarını oluşturur. Her grup daha sonra eskisinin yerini alan yeni bir sonuç tablosunda tek bir satıra indirgenir.

Bu, GROUP BY yan tümcesi için NULL = NULL, 3VL'de olduğu gibi NULL olarak değerlendirilmediği, ancak TRUE olarak değerlendirildiği anlamına gelir.

SQL standardı kafa karıştırıcı:

ORDER BY ve NULL'lar (329)

NULL olan bir sıralama anahtarı değerinin NULL olmayan bir değerden büyük veya küçük olarak kabul edilip edilmeyeceği uygulama tanımlıdır, ancak ...

... Her iki şekilde de yapan SQL ürünleri var.

Mart 1999'da Chris Farrar, geliştiricilerinden birinin sorduğu ve SQL Standardının anladığımı sandığım bir bölümünü incelemesine neden olan bir soruyu gündeme getirdi . Chris , spesifikasyonun genel anlayışıyla gerçek ifadesi arasında bazı farklılıklar buldu .

Ve bunun gibi. Celko tarafından yeterli olduğunu düşünüyorum.

SQL NULL'larında CJ Tarihi

CJ Date, NULL'lar hakkında daha radikaldir: SQL'de NULL'lardan kaçının, nokta. Aslında, SQL ve İlişkisel Teorisi: Doğru SQL Kodu Nasıl Yazılır'ın 4. bölümü, "ÇİFTLEME YOK, BOŞLUK YOK" başlıklı, "4.4 Boşlukların Nesi Yanlış?" ve "4.5 SQL'de Boş Değerlerden Kaçınma" (bağlantıyı takip edin: Google Kitaplar sayesinde bazı sayfaları çevrimiçi olarak okuyabilirsiniz).

Fabian Pascal, SQL NULLs üzerinde

Onun itibaren Veritabanı Yönetimi Pratik Sorunları - Düşünme Pratisyen için bir Başvurusu (hiçbir alıntılar on-line, üzgünüm):

10.3 Pratik Çıkarımlar

10.3.1 SQL NULL'leri

... SQL, 3VL'nin doğasında bulunan sorunların yanı sıra pek çok tuhaflık, komplikasyon, mantıksızlık ve doğrudan hatalardan muzdariptir [10, 11]; aralarında şunlar yer almaktadır:

  • Toplama işlevleri (örneğin, SUM (), AVG ()) NULL'leri yoksayar (COUNT () hariç).
  • Satırları olmayan bir tablodaki skaler bir ifade, 0 yerine hatalı olarak NULL olarak değerlendirilir.
  • "NULL = NULL" ifadesi NULL olarak değerlendirilir, ancak aslında SQL'de geçersizdir; yine de ORDER BY, NULL'ları eşit kabul eder ("normal" değerlerden önce veya sonra gelen her şey DBMS satıcısına bırakılır).
  • "X IS NOT NULL" ifadesi, 2VL'de olduğu gibi "NOT (x IS NULL)" 'a eşit değildir.

...

Ticari olarak uygulanan tüm SQL lehçeleri bu 3VL yaklaşımını izler ve bu nedenle, yalnızca bu sorunları ortaya çıkarmakla kalmaz , aynı zamanda ürünlere göre değişen özel uygulama sorunları da vardır .


4
"Ve benim açımdan şu: NULL, değer olarak" garip bir canavar "." - çünkü NULLbir değer değil.
Pavel Minaev

1
Ayrıca SQL Server vermiyor (NULL = NULL) -> FALSE. Belgeleri alıntılamak için ANSI_NULLS: "AÇIK belirtildiğinde, boş değere yapılan tüm karşılaştırmalar BİLİNMİYOR olarak değerlendirilir . KAPALI belirtildiğinde, UNICODE olmayan değerlerin boş bir değerle karşılaştırılması, her iki değer de NULL ise DOĞRU olarak değerlendirilir."
Pavel Minaev

@Pavel Minaev: a) ve DOĞRU, YANLIŞ'tan ne kadar iyidir? b) Bir değer değilse neden değişken değerlerin bir parçası olarak atanır?
MaD70

1
>> Aralık olduğu için mevsimlik bir örnek verelim. Ağacın altında iki hediyem var. Şimdi bana aynı şeyden iki tane alıp almadığımı söyle. ..... evet, iki şeye sahip olduğunuz ölçüde yaptınız ve şu anda ilgilendiğiniz kadarıyla , şu anki bilgilerinize göre, bunlar tamamen sizin için aynı
Brad Thomas

3
null = null doğru olmalıdır. boş olabilir değeri iyi tanımlı temsil bir bilinmeyen bir değer, ama aynı zamanda olabilir temsil yokluğu bir değer. Null değerinin neyi temsil ettiğine karar vermek geliştiriciye bağlı olmalıdır, ancak null'un kendisi kesinlikle bir değerdir ve null, null = null'dur. Başka herhangi bir uygulama felaketle sonuçlanır, çünkü üçlü mantığı temelde Boole olan yüklemlere yerleştiriyorsunuz. Bunun SQL sunucusundaki ayarlarda kalıcı hale geldiğine DİKKAT EDİYORUM. KAPALI KAPALI KAPALI onunla.
Triynko

10

Sırf iki şeyin ne olduğunu bilmiyor olman, onların eşit oldukları anlamına gelmez. Aklınıza ne zaman olursa NULLsize “Boş” (string) düşünmek sonra muhtemelen Postgresql en gibi eşitlik farklı bir test istiyorIS DISTINCT FROM VEIS NOT DISTINCT FROM

Gönderen üzerine PostgreSQL docs "Karşılaştırma İşlevleri ve Operatörleri"

ifade IS DISTINCT FROM ifadesi

ifade IS NOT DISTINCT FROM ifadesi

Boş olmayan girişler IS DISTINCT FROMiçin <>operatör ile aynıdır . Bununla birlikte, her iki girdi de boşsa, yanlış döndürür ve yalnızca bir girdi boşsa, doğru döndürür. Benzer şekilde, boş olmayan girişler için IS NOT DISTINCT FROMaynıdır =, ancak her iki giriş de boş olduğunda doğru ve yalnızca bir giriş boş olduğunda yanlış döndürür. Bu nedenle, bu yapılar, "bilinmeyen" yerine boş değer normal bir veri değeriymiş gibi etkili bir şekilde hareket eder.


9

Belki değişir, ancak NULL ile yapılan çoğu işlemi bir işlenen olarak NULL=NULLdeğerlendireceğini düşündüm NULL.


5

NULL kavramı, en hafif tabirle tartışmalı. Codd, ilişkisel modeli ve NULL kavramını bağlam içinde tanıttı (ve birden fazla tür NULL önermeye devam etti!) Bununla birlikte, Codd'un orijinal yazılarından bu yana ilişkisel teori gelişti: önerilerinin bazıları o zamandan beri bırakıldı (örneğin birincil anahtar) ve diğerleri asla yakalanmadı (örneğin, teta operatörleri). Modern ilişkisel teoride (gerçekten ilişkisel teoride, vurgulamalıyım) NULL sadece mevcut değildir. Üçüncü Manifesto'ya bakın. http://www.thethirdmanifesto.com/

SQL dili geriye dönük uyumluluk sorunu yaşamaktadır. NULL, SQL'de yolunu buldu ve biz buna bağlı kaldık. Muhtemelen, NULLSQL'de uygulanması kusurludur (SQL Server'ın uygulaması, ANSI_NULLSseçeneği nedeniyle işleri daha da karmaşık hale getirir ).

Temel tablolarda NULLable sütunların kullanımından kaçınmanızı öneririm.


Belki de baştan çıkarılmamam gerekse de, sadece NULLSQL'de nasıl çalıştığına dair kendi düzeltmelerimi yapmak istedim :

NULL= olarak NULLdeğerlendirilir UNKNOWN.

UNKNOWN mantıksal bir değerdir.

NULL bir veri değeridir.

Bunu kanıtlamak kolaydır, örneğin

SELECT NULL = NULL

doğru bir şekilde SQL Server'da bir hata oluşturur. Sonuç bir veri değeri olsaydı NULL, buradaki bazı yanıtların (yanlış bir şekilde) önerdiği gibi görmeyi beklerdik .

Mantıksal değer UNKNOWN, sırasıyla SQL DML ve SQL DDL'de farklı şekilde ele alınır.

SQL DML'de, UNKNOWNsatırların sonuç kümesinden kaldırılmasına neden olur.

Örneğin:

CREATE TABLE MyTable
(
 key_col INTEGER NOT NULL UNIQUE, 
 data_col INTEGER
 CHECK (data_col = 55)
);

INSERT INTO MyTable (key_col, data_col)
   VALUES (1, NULL);

INSERTOlsa bile, bu satır için başarılı CHECKkoşul olarak çözümlenir NULL = NULL. Bu, SQL-92 ("ANSI") Standardında tanımlanmıştır:

11.6 tablo kısıtlaması tanımı

3)

Tablo kısıtı bir denetim kısıtı tanımıysa, o zaman SC'nin hemen denetim kısıtı tanımında bulunan arama koşulu olmasına izin verin ve T, karşılık gelen tablo kısıtı tanımlayıcısında bulunan tablo adı olsun; tablo kısıtlaması ancak ve ancak

VAR (SEÇ * * NEREDE OLMADAN (SC))

doğru.

Mantığı izleyerek bunu dikkatlice tekrar okuyun.

Sade bir İngilizceyle, yukarıdaki yeni satırımıza varoluşla ilgili 'şüphenin faydası' UNKNOWNverilir ve geçmesine izin verilir.

SQL DML'de, WHEREyan tümce kuralının izlenmesi çok daha kolaydır:

Arama koşulu, her T satırına uygulanır. Where cümlesinin sonucu, arama koşulunun sonucunun doğru olduğu T'nin satırlarının bir tablosudur.

Düz İngilizce olarak, olarak değerlendirilen satırlar sonuç UNKNOWNkümesinden kaldırılır.


5

at technet nasıl boş değerler çalışma için iyi bir açıklaması var.

Boş, bilinmeyen anlamına gelir.

Bu nedenle Boolean ifadesi

değer = boş

false olarak değerlendirilmez, boş olarak değerlendirilir, ancak bu bir where cümlesinin nihai sonucuysa, hiçbir şey döndürülmez. Bu, bunu yapmanın pratik bir yoludur, çünkü boşa dönmeyi düşünmek zor olacaktır.

İlginç ve çok önemliAşağıdakileri anlamak :

Bir sorguda varsa

where (value=@param Or @param is null) And id=@anotherParam

ve

  • değer = 1
  • @param boş
  • id = 123
  • @ anotherParam = 123

sonra

"değer = @ param" null olarak değerlendirilir
"@param null" doğru olarak değerlendirilir
"id = @ anotherParam" doğru olarak değerlendirilir

Böylece değerlendirilecek ifade olur

(boş veya doğru) Ve doğru

Burada "null Or true" nun null olarak değerlendirileceğini ve böylece tüm ifadenin boş hale geleceğini ve satırın geri dönmeyeceğini düşünmek cazip gelebilir.

Bu öyle değil. Neden?

"Null Or true", doğru olarak değerlendirildiği için, ki bu çok mantıklıdır, çünkü eğer bir işlenen Or-işleci ile doğruysa, diğer işlenenin değeri ne olursa olsun, işlem true döndürür. Bu nedenle, diğer işlenenin bilinmemesi (boş) önemli değildir.

Sonunda true = true değerine sahibiz ve böylece satır döndürülecektir.

Not: "null Or true" nun doğru olarak değerlendirildiği kristal berraklığında mantıkla "null And true", null olarak değerlendirilir.

Güncelleme:
Tamam, sadece tamamlamak için geri kalanını da buraya eklemek istiyorum, bu da yukarıdakilere göre oldukça eğlenceli.

"null Or false", null, "null And false" ise yanlış olarak değerlendirilir. :)

Mantık elbette eskisi kadar aşikârdır.


5

Buradaki cevapların tümü CS perspektifinden geliyor gibi görünüyor, bu yüzden geliştirici perspektifinden bir tane eklemek istiyorum.

Bir geliştirici için NULL çok kullanışlıdır. Buradaki cevaplar NULL'un bilinmeyen anlamına geldiğini söylüyor ve belki de CS teorisinde bu doğru, hatırlamayın, uzun zaman oldu. Gerçek geliştirmede, en azından benim deneyimime göre, bu zamanın yaklaşık% 1'inde oluyor. Kalan% 99'u ise değerin BİLİNMEDİĞİ ancak YOK OLMASININ BİLİNMESİNİN BİLİNEN olduğu durumlarda kullanılır.

Örneğin:

  • Client.LastPurchase, yeni bir müşteri için. Bilinmeyen değil, henüz alım yapmadığı biliniyor.

  • Sınıf Başına Tablo Hiyerarşi eşlemesine sahip bir ORM kullanırken , bazı değerler belirli sınıflar için eşlenmez.

  • Bir ağaç yapısını eşlerken bir kök genellikleParent = NULL

  • Ve daha fazlası...

Eminim çoğu geliştirici bir noktada yazdı WHERE value = NULL, herhangi bir sonuç alamadı ve söz IS NULLdizimini bu şekilde öğrendiler . Sadece bu sorunun ve bağlantılı olanların kaç oyu olduğuna bakın.

SQL Veritabanları bir araçtır ve kullanıcılarının anlayabileceği en kolay şekilde tasarlanmalıdır.


1
Görünüşe göre herkes “BOŞ bilinmiyor” diye bağırıyor ve ardından davranışı haklı çıkarıyor. Evet, eğer bu bir öncülse, o zaman 3VL belki yanıttır. Ancak üzerinde çalıştığım neredeyse tüm DB'lerde NULL, yok anlamına gelir. Vahşi doğada sesin kaybolduğu için üzgünüm @AlexDev
John Rees

4

Çünkü NULL'bilinmeyen değer' anlamına gelir ve iki bilinmeyen değer eşit olamaz.

Yani, mantığımıza göre NULLN ° 1, NULLN ° 2'ye eşitse , bunu bir şekilde söylemeliyiz:

SELECT 1
WHERE ISNULL(nullParam1, -1) = ISNULL(nullParam2, -1)

bilinen değer -1N ° 1, -1N ° 2'ye eşittir


nullParam1 = -1ve nullParam2 =NULLuçak kazası .... olmalıISNULL(NULLIF(@nullParam1, @nullParam2), NULLIF(@nullParam2, nullParam1)) IS NULL
Selvin

4

MSDN, boş değerler ve oluşturdukları üç durum mantığı hakkında güzel bir açıklayıcı makaleye sahiptir .

Kısacası, SQL92 belirtimi NULL'u bilinmeyen olarak tanımlar ve aşağıdaki işleçlerde kullanılan NULL, başlatılmamışlar için beklenmeyen sonuçlara neden olur:

= operator NULL   true   false 
NULL       NULL   NULL   NULL
true       NULL   true   false
false      NULL   false  true

and op     NULL   true   false 
NULL       NULL   NULL   false
true       NULL   true   false
false      false  false  false

or op      NULL   true   false 
NULL       NULL   true   NULL
true       true   true   true
false      NULL   true   false

Ancak soru 3VL (üç değerli mantık) ile ilgili değil, eşitliğin dönüşlü özelliği ile ilgili.
MaD70

Daha kesin olmak gerekirse, sonunda cevabımda detaylandırdığım gibi, eşitlik bir 3VL'de yorumlandığında sorunlar ortaya çıkar, böylece eşitliğin refleksif özelliği her zaman doğru olarak değerlendirilmez.
MaD70

3

NULL hiçbir şeye eşit değildir, kendisi bile. NULL'un davranışını anlamak için benim kişisel çözümüm, onu mümkün olduğunca kullanmaktan kaçınmaktır :).


1
sol / sağ / dış birleşimlerde olduğu gibi her şeye eşit olabilir ...
Miguel Ventura

5
Ne kadar aptalca, verimsiz bir cevap. Aynı şey ilkokul çağındaki çocuklara cebir hakkında da söylenebilirdi, ancak onu çözmeye çalışan şeyi gerçekten kabul etmeden aptalca çıkacaktı, ki öyle oldu.
Evan Carroll

2
@Evan: Aslında, NULL'dan kaçınmak sağlam bir çözüm. 3 değerli mantık tartışmasız değildir ve birçok kişi SQL'in NULL olmadan ve gerektirdiği tüm (gerekli) karmaşıklık olmadan daha iyi olacağını düşünür.
sleske

3
"Pek çok insan" gelincik bir kelimedir ve "tartışmasız değil", 3VL'nin olmadığı daha basit olan "tartışmalı" olanı gizlemenin bir yoludur.
Evan Carroll

"NULL hiçbir şeye eşit değildir, kendisi bile." bu mantığa göre <somevalue>! = NULL true döndürmelidir. Ancak SQL'in garip evreninde bu yanlıştır.
Tom Lint

3

Soru:
Bir bilinmeyen başka bir bilinmeyene eşit mi?
(NULL = NULL)
Bu soru hiç kimsenin cevaplayamayacağı bir şeydir, bu nedenle ansi_nulls ayarınıza bağlı olarak varsayılan olarak true veya false olur.

Ancak soru şu:
Bu bilinmeyen değişken bilinmiyor mu?
Bu soru oldukça farklıdır ve doğru olarak cevaplanabilir.

nullVariable = null, değerleri karşılaştırıyor
nullVariable is null, değişkenin durumunu karşılaştırıyor


3

Karışıklık, NULL kullanımından kaynaklanan dolaylılık (soyutlama) seviyesinden kaynaklanır .

"Noel ağacının altında ne var" benzetmesine geri dönecek olursak, "Bilinmeyen" Kutu A'da ne olduğu hakkındaki bilgi durumunu açıklar.

Yani Kutu A'da ne olduğunu bilmiyorsanız, "Bilinmeyen" diyorsunuz ama bu kutunun içinde "Bilinmeyen" olduğu anlamına gelmez . Kutunun içinde bilinmeyenden başka bir şey var, muhtemelen bir tür nesne veya muhtemelen kutuda hiçbir şey yok.

Benzer şekilde, Kutu B'de ne olduğunu bilmiyorsanız, içerikler hakkındaki bilgi durumunuzu "Bilinmeyen" olarak etiketleyebilirsiniz.

İşte önemli nokta: Kutu A hakkındaki bilgi durumunuz, Kutu B hakkındaki bilgi durumunuza eşittir . (Her iki durumda da bilgi durumunuz "Bilinmeyen" veya "Kutuda ne olduğunu bilmiyorum" şeklindedir.) Ancak kutuların içeriği eşit olabilir veya olmayabilir.

SQL'e geri dönersek, ideal olarak değerleri yalnızca ne olduklarını bildiğiniz zaman karşılaştırabilmelisiniz. Ne yazık ki, bilgi eksikliğini tanımlayan etiket hücrenin kendisinde saklanıyor , bu yüzden onu bir değer olarak kullanmak istiyoruz. Ancak bunu bir değer olarak kullanmamalıyız, çünkü bu, "Kutu A'nın içeriği, Kutu A'da ne olduğunu bilmediğimizde ve / veya Kutu B'de ne olduğunu bilmediğimizde Kutu B'nin içeriğine eşittir" sonucuna yol açacaktır. (Mantıksal olarak, "Kutu A'da ne olduğunu bilmiyorsam ve Kutu B'de ne olduğunu bilmiyorsam, Kutu A'da ne var? Kutu B'de ne var" yanlıştır.)

Yaşasın, Ölü At.


1

null, sql'de bilinmiyor, bu nedenle iki bilinmeyenin aynı olmasını bekleyemeyiz.

Bununla birlikte, ANSI_NULLS'u Kapalı (Varsayılan olarak Açık) ayarlayarak bu davranışı elde edebilirsiniz. Boş değerler için = işlecini kullanabileceksiniz.

SET ANSI_NULLS off
if null=null
print 1
else 
print 2
set ansi_nulls on
if null=null
print 1
else 
print 2

2
Bu her türlü hayır . Dünyanın bir tanımı vardır null, onu anlamayı öğrenin ya da sadece int türlerine sahip olmak ve sütunları güncellemek için tabloyu değiştirin.
Evan Carroll

3
SET ANSI_NULLS'u gerçekten önermedim. ANSI_NULLS'u zor yoldan öğrendim. Ancak, burada SomeId = null yazan bir satırla karşılaştığınızda özellikle mevcut olan tüm seçenekleri bilmek her zaman iyidir ANSI_NULLS'u bilmeden bu satırı nasıl anlamlandırırsınız.
Görünüşe göre yazım

1

Vatandaşlarla ilgili bilgilerin kaydedilmesi için hükümet için çalışıyorsunuz. Bu, ülkedeki her kişinin ulusal kimliğini içerir. Yaklaşık 40 yıl önce bir kilisenin kapısına bir çocuk kalmıştı, kimse anne babasının kim olduğunu bilmiyor. Bu kişinin babasının kimliği NULL. Böyle iki insan var. Aynı baba kimliğini en az bir kişiyle (kardeş olan kişiler) sayın. Bu ikisini de sayıyor musun?

Cevap hayır, yapmıyorsunuz çünkü onların kardeş olup olmadıklarını bilmiyoruz.

Bir NULLseçeneğiniz olmadığını varsayalım ve bunun yerine "bilinmeyen" i temsil etmek için önceden belirlenmiş bir değer, belki boş bir dize veya 0 sayısı veya * karakteri vb. Kullanın. O zaman sorgularınızda * = * , 0 = 0 ve “” = “” vb. İstediğiniz bu değil (yukarıdaki örnekte olduğu gibi) ve bu vakaları sıklıkla unutabileceğiniz gibi (yukarıdaki örnek, sıradan günlük düşüncenin dışında ), o zaman sizin için NULL = NULLdoğru olmayan bir dile ihtiyaç duyarsınız .

Zorunluluk icatların anasıdır.


0

Diğer harika cevaplara bir ek:

AND: The result of true and unknown is unknown, false and unknown is false,
while unknown and unknown is unknown.

OR: The result of true or unknown is true, false or unknown is unknown, while unknown or unknown is unknown.

NOT: The result of not unknown is unknown

0

İki NULL için true döndüren bir ifade arıyorsanız, kullanabilirsiniz:

SELECT 1 
WHERE EXISTS (
    SELECT NULL
    INTERSECT
    SELECT NULL
)

Verileri bir tablodan diğerine kopyalamak istiyorsanız yararlıdır.


0

Eşitlik testi, örneğin bir case deyiminde when clause,

XYZ = NULL 

-e

XYZ IS NULL

Boşlukları ve boş dizeleri NULL'a eşit olarak değerlendirmek istersem, genellikle aşağıdaki gibi bir eşitlik testi de kullanırım:

(NULLIF(ltrim( XYZ ),'') IS NULL)

0

Noel benzetmesinden tekrar alıntı yapacak olursak:

SQL'de NULL, temelde "kapalı kutu" (bilinmeyen) anlamına gelir . Bu nedenle, iki kapalı kutuyu karşılaştırmanın sonucu da bilinmeyecektir (boş).

Bir geliştirici için bunun mantıksız olduğunu anlıyorum, çünkü programlama dillerinde genellikle NULL daha çok "boş kutu" (bilinen) anlamına gelir . Ve iki boş kutuyu karşılaştırmak doğal olarak doğru / eşit sonucunu verecektir.

Örneğin JavaScript'in nullve undefined.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.