NULL Yani "Bilinmiyor"
SQLite'taki diğer her değer somut bir şeyi temsil eder: bir sayı, bir metin ya da bir blob. Ama NULL farklı bir şeydir. Eksik ya da bilinmeyen bir değerin yerini tutan bir işarettir. NULL'un sorgularda neden bu kadar tuhaf davrandığını aslında tek başına bu fikir açıklıyor.
Üzerinde denemeler yapmak için küçük bir tablo hazırlayalım:
İki sütun NULL değer alabiliyor. Boris'in e-postası yok. Cleo'nun yaşı yok. Dan'in ise ne yaşı ne de e-postası var. Sayfanın geri kalanı, böyle satırları tuzağa düşmeden nasıl sorgulayacağınızla ilgili.
= ve <> ile NULL karşılaştırma çalışmaz
İlk akla gelen WHERE email = NULL yazmak oluyor. Mantıklı duruyor ama hiçbir şey döndürmüyor:
Sıfır satır döndü — oysa Boris ile Dan'in e-posta alanları açıkça null. Sebebi şu: NULL ile herhangi bir şeyi karşılaştırdığınızda sonuç true ya da false değil, yine NULL olur. SQLite'taki WHERE koşulu ise sadece sonucu true olan satırları döndürür; NULL true sayılmaz. Dolayısıyla bu satırlar elenir.
<> operatöründe de aynı tuzak geçerli:
Bunun Ada dışındaki herkesi döndürmesini beklersiniz. Ama sadece Cleo gelir. E-postası null olan Boris ve Dan listeden düşer — çünkü NULL <> 'ada@example.com' ifadesi de NULL üretir, true değil.
Bu, SQL'in en sık karşılaşılan tuzağıdır. Bir sorgu beklemediğiniz şekilde "satır kaybediyorsa", ilk şüpheleneceğiniz şey null içeren bir sütun olmalı.
IS NULL ve IS NOT NULL ile null kontrolü
SQLite'ta null kontrolü yapmanın doğru yolu IS operatörüdür. = operatörünün aksine, null'ı tanır ve her zaman true ya da false döndürür — asla null değil:
İlk sorgu Boris ve Dan'ı döndürür. İkincisi ise Ada ve Cleo'yu getirir. IS NULL ve IS NOT NULL, tam olarak "bu değer eksik mi?" sorusunu sormak için tasarlanmış iki operatördür. = NULL veya <> NULL yazma dürtüsü hissettiğiniz her yerde bunları kullan.
"Ada olmayanlar, bilinmeyenler de dahil" demek istiyorsanız kontrolleri açıkça birleştirmeniz gerekir:
Sonunda Boris, Cleo ve Dan da listeye dahil oluyor.
NULL, Aritmetik ve Birleştirme İşlemlerinde Yayılır
Bu "bilinmiyor" kuralı yalnızca karşılaştırmalarla sınırlı değil. NULL'a dokunan her işlem yine NULL üretir:
next_year ve doubled sütunları Cleo ile Dan için null. labelled_age de aynı şekilde null — çünkü bir string'i NULL ile birleştirdiğinizde sonuç 'Age: ' olmaz, NULL olur. Bir sütun null olabiliyorsa ve sonunda kullanılabilir bir değer elde etmek istiyorsanız, bu durumu açıkça ele almanız gerekir. İşte tam burada devreye iki fonksiyon giriyor.
IFNULL: İki Argümanlı Yedek Değer
IFNULL(a, b) fonksiyonu, a null değilse a'yı döndürür; null ise b'yi döndürür. Null bir değeri varsayılanla değiştirmenin en pratik yolu budur:
Boris ve Dan için sonuç (e-posta yok) oluyor. Cleo ile Dan için ise 0 dönüyor. Tablodaki asıl veriler değişmiyor — IFNULL yalnızca çıktıyı yeniden yazıyor.
IFNULL her zaman tam olarak iki argüman alır. Daha fazla yedek değere ihtiyacın varsa COALESCE devreye girer.
COALESCE: İlk NULL olmayan değer kazanır
COALESCE(a, b, c, ...) argümanları baştan sona tarar ve null olmayan ilk değeri döndürür. Yani IFNULL'un istediğiniz kadar yedek değerle çalışan genel hâli:
Ada ve Cleo için e-posta adresi kullanılıyor. Boris ve Dan'in e-postası NULL olduğundan SQLite ikinci argümana geçiyor: isimden türetilmiş bir adres. Eğer o da NULL olsaydı, sıra 'anonim' değerine gelecekti.
COALESCE, taşınabilir olan tercihtir; tüm büyük SQL veritabanları aynı şekilde destekler. IFNULL ise yalnızca iki argümanlı durumlar için SQLite ve MySQL'in sunduğu bir kısayol. Varsayılan olarak COALESCE kullanın; IFNULL'a yalnızca gerçekten iki argümanınız varsa ve daha kısa bir isim istiyorsanız başvurun.
SQLite NULL ve Boş String Farkı
Sık karşılaşılan bir kafa karışıklığı: NULL ile '' aynı şeymiş gibi davranılır. Oysa değiller.
'' aslında sıfır karakterlik gerçek bir string'dir. NULL ise değerin hiç olmaması demektir. length('') sonucu 0'dır; ama length(NULL) yine NULL döner. Üstelik NULL = NULL ifadesi 1 değil, NULL üretir — IS NULL'ın var olma sebebi tam olarak budur.
Bir sütun hem '' hem NULL tutabiliyorsa, "eksik veri"yi hangisiyle temsil edeceğine baştan karar ver ve ona sadık kal. İkisini birden kullanırsanız her sorguda iki durumu da ele almak zorunda kalırsınız ve eninde sonunda birini unutursun.
IN, NOT IN ve DISTINCT ile NULL davranışı
NULL'ın seni gafil avlayabileceği birkaç yer daha var.
İçinde null bulunan bir listeyle IN kullanmak şaşırtıcı sonuçlar verebilir; özellikle NOT IN ile:
Herkesin yaşı 25 olmayanları getireceğini düşünebilirsiniz. Ama hiçbir sonuç gelmez. SQLite, NOT IN (25, NULL) ifadesini kabaca age <> 25 AND age <> NULL şeklinde açar; age <> NULL ise her zaman NULL döner — yani koşul asla doğru olmaz. Çözüm, karşılaştırma yapılmadan önce listeden (ya da sütundan) NULL değerleri ayıklamaktır.
Öte yandan DISTINCT, tekrarları elerken NULL değerlerini birbirine eşit kabul eder:
Üç satır dönüyor: Ada'nın e-postası, Cleo'nun e-postası ve Boris ile Dan'in birleşmesinden gelen tek bir NULL. Aynı durum GROUP BY ve UNION için de geçerli — bunlar null değerleri tek bir grup olarak ele alır; yani = operatörünün yaptığının tam tersi. SQL bu konuda her zaman tutarlı değildir; hangi operatörün hangi tarafta durduğunu bilmek işinize yarar.
Hızlı Kontrol Listesi
- Eksik değerleri
IS NULL/IS NOT NULLile kontrol edin. Asla= NULLyazmayın. NULLiçeren her aritmetik işlem, birleştirme veya karşılaştırmaNULLdöner.- Null değerleri varsayılan bir değerle değiştirmek için
COALESCE(a, b, c, ...)kullanın. İki argümanlı kısa yol içinseIFNULL(a, b)var. - Boş string
''ileNULLaynı şey değildir. Her sütunda "eksik" için bunlardan birini seçin ve ona sadık kalın. NOT IN (..., NULL)neredeyse her zaman bir hatadır. Önce listeden null'ları temizleyin.
Sırada: Sonuçları Sıralama
Satırları doğru şekilde — null olanlar dahil — filtreleyebildiğinize göre, sıradaki adım onları anlamlı bir düzene koymak. Bir sonraki sayfada ORDER BY var ve sıralanmış bir sonuçta null'ların nereye düşeceği konusunda kendine has fikirleri var.
Sıkça Sorulan Sorular
SQLite'ta neden column = NULL çalışmıyor?
column = NULL çalışmıyor?Çünkü NULL "bilinmeyen" anlamına gelir ve bilinmeyen bir şeyle yapılan her karşılaştırmanın sonucu da bilinmeyendir — yani true değil. Bu yüzden WHERE col = NULL ifadesi, sütun gerçekten null olsa bile hiçbir satırı döndürmez. Bunun yerine WHERE col IS NULL kullanmalısınız. Aynı şey <> için de geçerli: doğrusu IS NOT NULL.
SQLite'ta IFNULL ile COALESCE arasındaki fark nedir?
IFNULL(a, b) tam olarak iki argüman alır; a null değilse a'yı, null ise b'yi döndürür. COALESCE(a, b, c, ...) ise istediğiniz kadar argüman alır ve null olmayan ilk değeri döndürür. Yani IFNULL, iki argümanlı kısa bir kullanımdan ibaret; COALESCE ise daha genel hâli ve neredeyse tüm SQL veritabanlarında ortak çalışır.
SQLite'ta NULL ile boş string aynı şey mi?
Hayır. NULL "hiçbir değer yok" demektir; '' ise uzunluğu sıfır olan, gerçek ve bilinen bir string'tir. '' IS NULL sorgusu 0 (false) döndürür; length('') sıfırken length(NULL) doğrudan NULL döner. Bir sütun her ikisine de izin veriyorsa, sorgularınızda bu iki durumu ayrı ayrı ele almalı ya da birini diğerine normalize etmelisiniz.