SQLite'ta NULL "bilinmeyen değer" anlamına gelir ve hiçbir değere, kendisine bile eşit değildir: NULL = NULL ifadesinin sonucu doğru değil yine NULL'dır. Bu yüzden NULL değerleri = ile değil, IS NULL ve IS NOT NULL ile ararsınız. Eksik değerleri bir varsayılanla değiştirmek için coalesce() veya ifnull(), belirli bir değeri NULL'a çevirmek için nullif() kullanılır.
NULL ile ilgili kuralların çoğu SQL standardından gelir, ama SQLite belgeleri standardın bazı noktalarda belirsiz olduğunu ve davranışın diğer veritabanlarıyla yapılan deneylerle belirlendiğini anlatır. Bu yazıda karşılaştırma, mantık işleçleri, IN ve NOT IN, özet fonksiyonları, sıralama ve kısıtlamalarda NULL'ın davranışını çalıştırılmış örneklerle tek tek ele alıyoruz.
NULL ile karşılaştırma: = yerine IS

Belgelere göre işleçlerin büyük çoğunluğu, işlenenlerinden biri NULL olduğunda NULL üretir. Toplama, çarpma, metin birleştirme ve karşılaştırma işleçlerinin hepsi bu kurala uyar; NULL ile sıfırın çarpımı bile NULL'dır. IS ve IS NOT işleçleri ise = ve != gibi çalışır, tek farkla: iki taraf da NULL ise IS 1, yalnızca biri NULL ise 0 döndürür. Bu işleçlerin sonucu hiçbir zaman NULL olmaz.
SELECT NULL = NULL, NULL <> 1, NULL IS NULL, NULL IS 1, 1 IS 1;
-- çıktı: ||1|0|1
SELECT NULL IS NOT DISTINCT FROM NULL, 2 IS DISTINCT FROM NULL;
-- çıktı: 1|1
SELECT typeof(NULL), typeof(NULL + 1), typeof(NULL * 0), typeof('a' || NULL);
-- çıktı: null|null|null|nullIS NOT DISTINCT FROM ve IS DISTINCT FROM, sırasıyla IS ve IS NOT işleçlerinin standart SQL yazımıdır ve SQLite 3.39.0 sürüm notu ile eklendi. Kısa IS biçimi SQLite'a özgüdür; sorgularınızın başka veritabanlarında da çalışması gerekiyorsa uzun biçimi kullanın. typeof() fonksiyonu NULL için null metnini döndürür; bir değerin gerçekten NULL mı yoksa boş metin mi olduğunu ayırt etmenin en kesin yolu budur.
Üç değerli mantık: AND, OR, NOT
NULL, mantık işleçlerinde "doğru mu yanlış mı bilinmiyor" anlamına gelir. Belgelerin belirttiği iki istisna sonucu kesinleştirir: AND işlecinin diğer tarafı yanlışsa sonuç yanlıştır, OR işlecinin diğer tarafı doğruysa sonuç doğrudur. Bunların dışındaki durumlarda sonuç NULL kalır; NOT NULL da NULL'dır.
SELECT NULL AND 0, NULL AND 1, NULL OR 1, NULL OR 0, NOT NULL;
-- çıktı: 0||1||
SELECT CASE WHEN NULL THEN 'evet' ELSE 'hayir' END,
CASE NULL WHEN NULL THEN 'esit' ELSE 'esit degil' END;
-- çıktı: hayir|esit degil
SELECT NULL IS TRUE, NULL IS FALSE, NULL IS NOT TRUE, 0 IS FALSE;
-- çıktı: 0|0|1|1CASE WHEN bölümünde NULL "doğru değil" kabul edildiği için ilk ifade ELSE dalına düştü. İkinci CASE biçiminde temel ifade NULL olduğunda belgelere göre sonuç her zaman ELSE dalıdır, çünkü karşılaştırma = kurallarıyla yapılır ve NULL hiçbir WHEN değerine eşit olmaz. Son satır daha az bilinen bir ayrıntıyı gösteriyor: IS TRUE ve IS FALSE sol tarafı mantıksal değer olarak yorumlar ve NULL ikisine de uymaz.
WHERE koşullarında NULL
WHERE yalnızca sonucu kesin olarak doğru olan satırları geçirir; sonucu yanlış veya NULL olan satırlar elenir. NULL değerli sütunlar içeren tablolarda bu kural, ilk bakışta mantıklı görünen sorguların satır kaybetmesine yol açar. Aşağıdaki müşteri tablosunda iki telefon ve iki şehir değeri NULL, Zeynep'in telefonu ise NULL değil boş metin.
CREATE TABLE musteri(id INTEGER PRIMARY KEY, ad TEXT, telefon TEXT, sehir TEXT);
INSERT INTO musteri VALUES
(1, 'Ayşe', '0532 000 00 01', 'Ankara'),
(2, 'Mehmet', NULL, 'İzmir'),
(3, 'Zeynep', '', NULL),
(4, 'Can', NULL, NULL);
SELECT ad FROM musteri WHERE telefon = NULL;
-- (hiç satır dönmez)
SELECT ad FROM musteri WHERE telefon IS NULL;
-- çıktı:
-- Mehmet
-- Can
SELECT ad FROM musteri WHERE sehir <> 'Ankara';
-- çıktı: Mehmet
SELECT ad FROM musteri WHERE sehir IS NOT 'Ankara';
-- çıktı:
-- Mehmet
-- Zeynep
-- Cansehir <> 'Ankara' koşulu yalnızca Mehmet'i döndürdü; şehri NULL olan Zeynep ve Can için karşılaştırma NULL üretti ve iki satır da elendi. "Ankara olmayan herkes" sorusunun doğru yazımı sehir IS NOT 'Ankara' veya sehir <> 'Ankara' OR sehir IS NULL biçimindedir. Bir koşul yazarken her zaman "bu sütun NULL olabilir mi?" diye sorun.
coalesce, ifnull, nullif ve iif
coalesce(X, Y, ...) argümanlarından NULL olmayan ilkini, hepsi NULL ise NULL döndürür ve en az iki argüman ister. ifnull(X, Y) tam olarak iki argüman alan aynı fonksiyondur. nullif(X, Y) ise ters yönde çalışır: iki argüman aynıysa NULL, farklıysa ilk argümanı döndürür. İkisini birlikte kullanmak, boş metni ve NULL'ı aynı biçimde ele almanın kısa bir yoludur.
SELECT ad, coalesce(telefon, 'yok') FROM musteri;
-- çıktı:
-- Ayşe|0532 000 00 01
-- Mehmet|yok
-- Zeynep|
-- Can|yok
-- Boş metni de eksik say: önce nullif ile NULL'a çevir
SELECT ad, coalesce(nullif(telefon, ''), 'yok') FROM musteri;
-- çıktı:
-- Ayşe|0532 000 00 01
-- Mehmet|yok
-- Zeynep|yok
-- Can|yok
SELECT ifnull(NULL, 'b'), coalesce(NULL, NULL, 3), coalesce(NULL, NULL);
-- çıktı: b|3|
SELECT iif(telefon IS NULL, 'eksik', 'tamam') FROM musteri;
-- çıktı:
-- tamam
-- eksik
-- tamam
-- eksikiif(koşul, değer1, değer2) bir CASE WHEN ifadesinin kısa yazımıdır ve belgelere göre aynı bayt kodunu üretir. SQLite 3.32.0 sürüm notu ile eklenen bu fonksiyon SQLite 3.48.0 sürüm notu ile iki argümanlı kullanıma ve if() takma adına, SQLite 3.49.0 sürüm notu ile de ikiden fazla koşul-değer çiftine kavuştu. Eski bir kütüphanede en güvenli seçenek CASE ifadesidir.
Metin birleştirme ve fonksiyonlarda NULL
|| işleci NULL ile karşılaştığında bütün sonucu NULL yapar; bu yüzden bir adres veya ad soyad birleştirmesi, parçalardan biri eksikse tamamen boş görünür. SQLite 3.44.0 sürüm notu ile gelen concat() fonksiyonu ise NULL argümanları yok sayar; bütün argümanlar NULL olsa bile boş metin döndürür. Aynı sürümle gelen concat_ws() de ayraçtan sonraki NULL argümanları atlar.
SELECT 'Tel: ' || telefon, concat('Tel: ', telefon) FROM musteri WHERE id IN (1, 2);
-- çıktı:
-- Tel: 0532 000 00 01|Tel: 0532 000 00 01
-- |Tel:
SELECT max(1, NULL, 3), min(1, NULL, 3);
-- çıktı: |
SELECT 10 / 0, 10 % 0, 10.0 / 0;
-- çıktı: ||Çok argümanlı max() fonksiyonu, belgelere göre argümanlardan biri NULL ise NULL döndürür; denememizde çok argümanlı min() da aynı sonucu verdi. Tek argümanlı min ve max ise birer özet fonksiyonudur ve NULL değerleri atlar; ikisini karıştırmamak gerekir. Son sorgu SQLite'a özgü bir davranışı gösteriyor: sıfıra bölme hata vermez, NULL üretir. Bir hesaplamanın neden NULL döndüğünü ararken bunu da aklınızda tutun.
IN ve NOT IN tuzağı

IN işlecinin NULL ile davranışı belgelerde bir tabloyla açıklanır. Sol taraftaki değer listede bulunursa sonuç doğrudur. Bulunmazsa ve listede NULL varsa sonuç yanlış değil NULL olur, çünkü bilinmeyen değerin aranan değer olup olmadığı bilinemez. Sol taraf NULL ise sonuç yine NULL'dır. Liste boşsa sol taraf NULL olsa bile IN yanlış, NOT IN doğru döndürür. Boş liste yazabilmek SQLite'a özgüdür; çoğu veritabanı en az bir öğe ister.
SELECT 1 IN (1, NULL), 2 IN (1, NULL), 2 NOT IN (1, NULL);
-- çıktı: 1||
SELECT NULL IN (), NULL NOT IN ();
-- çıktı: 0|1
CREATE TABLE kara_liste(sehir TEXT);
INSERT INTO kara_liste VALUES ('İzmir'), (NULL);
SELECT ad FROM musteri WHERE sehir NOT IN (SELECT sehir FROM kara_liste);
-- (hiç satır dönmez)
SELECT ad FROM musteri m
WHERE NOT EXISTS (SELECT 1 FROM kara_liste k WHERE k.sehir = m.sehir);
-- çıktı:
-- Ayşe
-- Zeynep
-- Can| Sol taraf | Liste | IN | NOT IN |
|---|---|---|---|
| NULL değil, listede var | Fark etmez | doğru | yanlış |
| NULL değil, listede yok | NULL içermiyor | yanlış | doğru |
| NULL değil, listede yok | NULL içeriyor | NULL | NULL |
| NULL | Boş değil | NULL | NULL |
| Fark etmez | Boş | yanlış | doğru |
Pratikte en tehlikeli satır üçüncüsüdür. Kara listede tek bir NULL değer bulunması, NOT IN alt sorgusunun hiçbir satır döndürmemesine yol açtı. Bu hata genellikle alt sorgunun döndürdüğü sütunda NULL olabileceği akla gelmediği için yapılır ve sorgu hata vermediğinden fark edilmesi zordur. Güvenli seçenekler iki tanedir: alt sorguya WHERE sehir IS NOT NULL eklemek veya yukarıdaki gibi NOT EXISTS kullanmak. Belgelere göre EXISTS alt sorgusundaki NULL değerler diğer değerlerden farklı işlem görmez; sonuç her zaman 0 veya 1'dir.
Özet fonksiyonları, DISTINCT ve GROUP BY
count(*) dışındaki özet fonksiyonları NULL değerleri hesaba katmaz. count(sutun) yalnızca NULL olmayan değerleri sayar; avg ortalamayı yalnızca NULL olmayan değerler üzerinden alır. Hiç NULL olmayan değer yoksa sum, avg, min ve max NULL döndürür, total ise 0.0.
SELECT count(*), count(telefon), count(sehir) FROM musteri;
-- çıktı: 4|2|2
SELECT sum(x), total(x), avg(x), count(x) FROM (SELECT NULL AS x);
-- çıktı: |0.0||0
SELECT DISTINCT sehir FROM musteri;
-- çıktı:
-- Ankara
-- İzmir
--
SELECT sehir, count(*) FROM musteri GROUP BY sehir;
-- çıktı:
-- |2
-- Ankara|1
-- İzmir|1DISTINCT ve GROUP BY NULL'lara karşılaştırmadan farklı davranır: ikisinde de bütün NULL değerler birbirine eşit sayılır ve tek bir satıra veya gruba toplanır. Belgeler bu kararın kökenini de anlatır: SQLite başlangıçta NULL'ları her yerde birbirinden farklı sayacak biçimde yazılmıştı, ancak diğer veritabanlarıyla yapılan deneylerde hiçbirinin SELECT DISTINCT ve UNION için böyle davranmadığı görüldü ve SQLite PostgreSQL, Oracle ve DB2 ile aynı davranışa getirildi. UNION da yinelenenleri ayıklarken NULL'ları eşit kabul eder. Özet fonksiyonlarının ayrıntıları için GROUP BY ve aggregate fonksiyonlar yazısına bakın.
Sıralamada NULL
SQLite sıralamada NULL'ı bütün değerlerden küçük kabul eder: artan sıralamada NULL'lar başta, azalan sıralamada sonda yer alır. NULLS FIRST ve NULLS LAST bu yerleşimi değiştirir ve SQLite 3.30.0 sürüm notu ile eklendi. Daha eski sürümlerde ORDER BY sehir IS NULL, sehir aynı işi görür.
SELECT ad, sehir FROM musteri ORDER BY sehir;
-- çıktı:
-- Zeynep|
-- Can|
-- Ayşe|Ankara
-- Mehmet|İzmir
SELECT ad, sehir FROM musteri ORDER BY sehir NULLS LAST, ad;
-- çıktı:
-- Ayşe|Ankara
-- Mehmet|İzmir
-- Can|
-- Zeynep|Sıralama ve sayfalama kuralları SQLite SELECT, WHERE, ORDER BY ve LIMIT yazısında ayrıntılı olarak anlatılıyor.
UNIQUE ve PRIMARY KEY sütunlarında NULL
Kısıtlamalar NULL'a yine farklı bir kuralla bakar. Belgelere göre UNIQUE kısıtında NULL değerler diğer bütün değerlerden, başka NULL'lar dahil, farklı kabul edilir. Bu yüzden UNIQUE bir sütuna istediğiniz kadar NULL ekleyebilirsiniz; aynı NULL olmayan değeri ikinci kez eklemek ise kısıt hatası verir. Belgelerdeki karşılaştırma tablosuna göre PostgreSQL ve Oracle da böyle davranırken bazı veritabanları UNIQUE sütunda NULL'ları eşit sayar; taşıma yaparken bunu kontrol edin.
CREATE TABLE uye(eposta TEXT UNIQUE);
INSERT INTO uye VALUES (NULL), (NULL), ('a@ornek.com');
SELECT count(*) FROM uye;
-- çıktı: 3
INSERT INTO uye VALUES ('a@ornek.com');
-- hata: UNIQUE constraint failed: uye.eposta
-- INTEGER PRIMARY KEY olmayan birincil anahtar NULL kabul eder
CREATE TABLE etiket(kod TEXT PRIMARY KEY, ad TEXT);
INSERT INTO etiket VALUES (NULL, 'birinci'), (NULL, 'ikinci');
SELECT count(*) FROM etiket WHERE kod IS NULL;
-- çıktı: 2
CREATE TABLE etiket2(kod TEXT PRIMARY KEY NOT NULL, ad TEXT);
INSERT INTO etiket2 VALUES (NULL, 'birinci');
-- hata: NOT NULL constraint failed: etiket2.kodİkinci örnek SQLite'ın belgelediği tarihsel bir sapmadır. SQL standardına göre birincil anahtar NULL olamaz, ancak erken sürümlerdeki bir hata yüzünden SQLite, sütun INTEGER PRIMARY KEY değilse, tablo WITHOUT ROWID veya STRICT değilse ve sütuna NOT NULL yazılmamışsa birincil anahtarda NULL'a izin verir. Eski uygulamaları bozmamak için bu davranış düzeltilmedi. Metin birincil anahtar kullanıyorsanız NOT NULL eklemeyi alışkanlık hâline getirin. Kısıtların geri kalanı CREATE TABLE ve kısıtlamalar ve PRIMARY KEY, rowid ve AUTOINCREMENT yazılarında.
Komut satırında NULL'ı görmek
sqlite3 aracı liste biçiminde NULL değerleri boş olarak yazar; bu yüzden NULL ile boş metni ekranda ayırt edemezsiniz. .nullvalue komutu NULL'ların yerine yazılacak metni belirler:
.nullvalue NULL
SELECT ad, telefon FROM musteri WHERE id IN (2, 3);
-- çıktı:
-- Mehmet|NULL
-- Zeynep|
.nullvalue ''Diğer çıktı ayarları için SQLite .mode çıktı biçimleri yazısına bakabilirsiniz.
Sık yapılan hatalar

= NULLyazmak: sonuç her zaman NULL'dır ve hiçbir satır dönmez;IS NULLkullanın.<>ile NULL satırları kaybetmek: "X olmayan herkes" içinIS NOTkullanın veyaOR sutun IS NULLekleyin.- NULL içerebilen bir alt sorguyla
NOT IN: sonuç boş kalır;NOT EXISTStercih edin. ||ile eksik parçaları birleştirmek: bir parça NULL ise bütün metin NULL olur;coalesce()veyaconcat()kullanın.- Boş kümede
sum()sonucunu 0 sanmak: sonuç NULL'dır;total()veyacoalesce(sum(x), 0)yazın.
Sık Sorulan Sorular
NULL ile boş metin arasındaki fark nedir?
Boş metin uzunluğu sıfır olan geçerli bir değerdir ve typeof('') sonucu text'tir. NULL ise değerin olmadığını gösterir ve typeof(NULL) sonucu null'dır. Karşılaştırmalar, count() ve UNIQUE kısıtı ikisine farklı davranır.
Bir sütunun NULL olmasını tamamen engelleyebilir miyim?
Evet, sütun tanımına NOT NULL ekleyin; isterseniz yanına bir DEFAULT değeri de yazın. Var olan bir sütuna sonradan NOT NULL eklemek ise SQLite'ta ancak yeni sürümlerde doğrudan desteklenir; ayrıntılar ALTER TABLE yazısında.
NULL değerler indekste yer alır mı?
NULL değerli satırların indekse girmesini istemiyorsanız WHERE sutun IS NOT NULL koşullu bir kısmi indeks oluşturabilirsiniz. Bu yöntem partial index ve ifade indeksi yazısında anlatılıyor.
Sıfıra bölme neden hata vermiyor?
SQLite sıfıra bölmeyi hata olarak değil, NULL sonuç olarak ele alır; yukarıdaki örnekte tamsayı, kalan ve ondalık bölmenin üçü de NULL döndürdü. Bölen değerin sıfır olabileceği hesaplarda sonucu coalesce() ile bir varsayılana çevirebilirsiniz.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: SQLite öğrenme rehberi · SQLite SELECT · GROUP BY ve aggregate · SQLite JOIN türleri · Veri tipleri ve type affinity · Metin fonksiyonları