Berk Akademi
Ana Sayfa
ÖZEL KODLAMA DERSLERİ
Yazılım Özel Ders
Tüm birebir programlara genel bakış
Python Yazılım Kursu
Sıfırdan ileri seviyeye birebir Python
Java Yazılım Kursu
OOP odaklı birebir Java eğitimi
AP Computer Science Principles
AP CSP sınav hazırlığı
GRUP DERSLERİ
Python & Django Masterclass
SINIRLI KONTENJAN
Java & Spring Boot Masterclass
SINIRLI KONTENJAN
C# .NET Masterclass
SINIRLI KONTENJAN
VİDEO DERSLER
Sıfırdan Temel Python Kursu
Kendi Hızında Öğren
ÜCRETSİZ
Seviye Testi
Ücretsiz — Python, Java, algoritma seviye testleri
Kariyerini Keşfet
Sertifika Doğrula
Belge numarası ve soyad ile doğrulama

SQL’de NOT IN ve NULL: Neden Hiç Sonuç Dönmez?

sqlde-not-in-null-neden-hic-s-sonuc-donmez
Bu yazıda neler var?
  1. NOT IN Neden Hiçbir Satır Döndürmüyor?
  2. NULL Karşılaştırmaları Neden TRUE veya FALSE Değil, UNKNOWN Üretir?
  3. Aynı Beş Satırlık Veride NOT IN Hatasını Adım Adım Görün
  4. NOT EXISTS Neden NULL Güvenli Bir Alternatiftir?
  5. LEFT JOIN ... IS NULL Ne Zaman Tercih Edilebilir?
  6. Kendi NULL Senaryonu Tahmin Et: Mini Alıştırma ve Kontrol Listesi
  7. Sık Sorulan Sorular

SQL NOT IN NULL davranışında sorgunun hiçbir satır döndürmemesinin temel nedeni, alt sorgudan gelen değerler arasında tek bir NULL bulunmasıdır. Bu durumda NOT IN içindeki karşılaştırmalardan biri UNKNOWN üretir; WHERE ise yalnızca sonucu TRUE olan satırları seçtiği için döndürülmesini beklediğiniz satırlar elenir.

Kısacası zihinsel modeliniz şu olabilir: Listeye NULL karıştıysa NOT IN güvenilir biçimde TRUE üretemeyebilir. Sorun alt sorgunun çalışmaması değil, SQL’in bilinmeyen değerlerle yaptığı karşılaştırmaların iki değil üç sonuçlu bir mantığa dayanmasıdır.

NOT IN Neden Hiçbir Satır Döndürmüyor?

NOT IN, bir değerin listedeki bütün değerlerden farklı olup olmadığını kontrol eder. Örneğin urun_id NOT IN (2, 4) koşulu, urun_id değerinin hem 2’den hem de 4’ten farklı olmasını ister.

Fakat liste (2, 4, NULL) biçimine geldiğinde SQL şu soruyla karşılaşır: “Bu ürün kimliği, ne olduğu bilinmeyen değerden farklı mı?” Bilinmeyen değer hakkında kesin bir karşılaştırma yapılamadığı için bu sorunun sonucu TRUE veya FALSE değil, UNKNOWN olur.

NULL, bir sütunda değerin bilinmediğini veya mevcut olmadığını ifade eder. Boş string ya da sıfır değildir. '' uzunluğu sıfır olan bir metin değeridir; 0 ise sayısal bir değerdir. Her ikisi de karşılaştırılabilirken NULL, karşılaştırılacak bilinen bir değer sunmaz.

Örneğin bir alt sorgunun 2, 4 ve NULL döndürdüğünü düşünün. Dış sorgudaki değer 7 olduğunda, 7’nin 2’den ve 4’ten farklı olduğu bilinir. Ancak 7’nin bilinmeyen değerden farklı olup olmadığı kesin olarak söylenemez. Koşul bu nedenle TRUE seviyesine ulaşamaz ve satır sonuç kümesine alınmaz.

NULL Karşılaştırmaları Neden TRUE veya FALSE Değil, UNKNOWN Üretir?

NULL Karşılaştırmaları Neden TRUE veya FALSE Değil, UNKNOWN Üretir?

SQL, NULL içeren karşılaştırmalarda üç değerli mantık kullanır: TRUE, FALSE ve UNKNOWN. Bilinmeyen bir değerin 5’e eşit veya 5’ten farklı olduğunu kanıtlayamadığınız için aşağıdaki karşılaştırmaların tamamı UNKNOWN üretir.

İfade Sonuç WHERE açısından etkisi
NULL = 5 UNKNOWN Satır seçilmez
NULL <> 5 UNKNOWN Satır seçilmez
NULL = NULL UNKNOWN Satır seçilmez
NULL <> NULL UNKNOWN Satır seçilmez

NULL = NULL ifadesinin bile TRUE olmaması önemlidir. İki değerin de bilinmiyor olması, bunların birbirine eşit olduğunu kanıtlamaz. NULL kontrolü bu nedenle = veya <> ile değil, amaca göre IS NULL ya da IS NOT NULL ile yapılır.

  • NULL, '' değildir; boş metin bilinen bir metin değeridir.
  • NULL, 0 değildir; sıfır bilinen bir sayısal değerdir.
  • NULL, “değer hakkında kesin bilgi yok” durumunu temsil eder.

NOT IN davranışını görmek için x NOT IN (a, b, NULL) ifadesini zihinsel olarak şu adımlarla açabilirsiniz:

  1. x değeri a ile karşılaştırılır: x <> a.
  2. x değeri b ile karşılaştırılır: x <> b.
  3. x değeri NULL ile karşılaştırılır: x <> NULL.
  4. Bu parçalar x <> a AND x <> b AND x <> NULL biçiminde birleşir.
  5. Son karşılaştırma UNKNOWN olduğunda, diğer parçalar TRUE olsa bile bütün koşul TRUE olamaz.

Örneğin 7 NOT IN (2, 4, NULL), mantıksal olarak TRUE AND TRUE AND UNKNOWN biçimine dönüşür. Sonuç UNKNOWN olur. WHERE yalnızca TRUE koşulları kabul ettiği için 7 değerini taşıyan satır da sonuç kümesinin dışında kalır.

Aynı Beş Satırlık Veride NOT IN Hatasını Adım Adım Görün

NOT IN neden hiçbir satır döndürmüyor? Çünkü alt sorgunun sonuç listesinde tek bir NULL bile varsa, SQL bazı karşılaştırmaları kesin olarak TRUE veya FALSE kabul edemez. Bunu görmek için aynı müşteri ve sipariş verilerini kullanalım.

Müşteri ID Müşteri adı
1 Ayşe
2 Burak
3 Ceren
4 Deniz
5 Emre
Sipariş ID Müşteri ID
101 1
102 3
103 5
104 NULL

Alt sorgu tek başına çalıştırıldığında 1, 3, 5 ve NULL değerlerini döndürür. Şimdi müşterisi siparişi olmayanları bulmayı deneyelim:

SELECT c.customer_id, c.name
FROM customers c
WHERE c.customer_id NOT IN (
    SELECT o.customer_id
    FROM orders o
);

Bu sorgunun beklenen çıktısı boş sonuç kümesidir. İlk bakışta 2 ve 4 numaralı müşterilerin gelmesi beklenir; ancak SQL, her müşteri için “ID, 1’e, 3’e, 5’e ve NULL’a eşit değil mi?” sorusunu değerlendirir. NULL ile yapılan karşılaştırma kesin bir sonuca ulaşamadığı için sonuç UNKNOWN olur. WHERE yalnızca TRUE olan satırları tuttuğundan 2 ve 4 de elenir.

Buradaki NULL, boş string ('') veya 0 değildir. NULL, değerin bilinmediğini ya da mevcut olmadığının belirtilmediğini ifade eder. Bu nedenle sayısal müşteri ID’leriyle normal bir değer gibi karşılaştırılamaz.

Alt sorgudaki belirsiz kaydı filtreleyerek NOT IN kullanımını bu örnekte düzeltebiliriz:

SELECT c.customer_id, c.name
FROM customers c
WHERE c.customer_id NOT IN (
    SELECT o.customer_id
    FROM orders o
    WHERE o.customer_id IS NOT NULL
);

Bu kez alt sorgu yalnızca 1, 3 ve 5 değerlerini döndürür. Beklenen sonuç 2 ve 4 numaralı müşterilerdir.

Sorgu NULL davranışı Beklenen müşteri ID'leri Teşhis
NOT IN Alt listede NULL varsa belirsizlik oluşur Hiçbiri NULL filtrelenmediği için sonuçlar elenir
NOT IN + IS NOT NULL NULL alt sorgudan çıkarılır 2, 4 Bu veri setinde doğru sonuç verir

NOT EXISTS Neden NULL Güvenli Bir Alternatiftir?

NOT EXISTS Neden NULL Güvenli Bir Alternatiftir?

NOT EXISTS, alt sorgudan dönen değerleri tek bir listeyle karşılaştırmaz. Bunun yerine her müşteri için, aynı müşteri ID’sine sahip en az bir sipariş satırı olup olmadığını kontrol eder. Eşleşme yoksa müşteri sonuçlara eklenir:

SELECT c.customer_id, c.name
FROM customers c
WHERE NOT EXISTS (
    SELECT 1
    FROM orders o
    WHERE o.customer_id = c.customer_id
);

Bu sorguda o.customer_id değeri NULL olan sipariş, hiçbir müşteriyle eşleşmez; fakat NULL, bütün sorgunun sonucunu belirsiz hâle getiren bir liste elemanı olarak kullanılmaz. Beklenen sonuç yine 2 ve 4 numaralı müşterilerdir.

Bu nedenle alt sorgunun NULL içerebilme ihtimali varsa NOT EXISTS çoğu durumda daha güvenli ve okunabilir bir seçimdir. NOT IN kullanacaksanız alt sorguda IS NOT NULL filtresini özellikle kontrol edin. NOT EXISTS otomatik olarak her sorguyu doğru hâle getirmez; korelasyon koşulu yanlış yazılırsa eşleşmeler hatalı değerlendirilir.

LEFT JOIN ... IS NULL Ne Zaman Tercih Edilebilir?

LEFT JOIN ... IS NULL, bir tablodaki kayıtların diğer tabloda karşılığı bulunmayanlarını seçmek için kullanılan anti-join yaklaşımıdır. Örneğin hiç sipariş vermemiş müşterileri bulmak için sorgu şu şekilde yazılabilir:

SELECT c.customer_id, c.name
FROM customers AS c
LEFT JOIN orders AS o
    ON o.customer_id = c.customer_id
WHERE o.order_id IS NULL;

Bu sorguda customers tablosundaki her müşteri korunur. Eşleşen sipariş varsa orders tarafındaki alanlar doldurulur; eşleşme yoksa sipariş tarafındaki sütunlar NULL olur. WHERE o.order_id IS NULL koşulu da yalnızca sipariş eşleşmesi bulunmayan müşterileri bırakır.

Burada kontrol edilen alanın orders.order_id gibi birincil anahtar veya normal koşullarda NULL olamayacak güvenilir bir satır kimliği olması önemlidir. Eğer sipariş tablosundaki isteğe bağlı bir alanı kontrol ederseniz, gerçekten sipariş eşleşmesi olduğu hâlde o alanın değeri NULL olduğu için müşteriyi yanlışlıkla “siparişsiz” kabul edebilirsiniz.

Üç yaklaşım arasında nasıl seçim yapılır?

  • NOT EXISTS: Eşleşme kontrolünü açık ve çoğu durumda kolay okunur biçimde ifade eder. Özellikle ilişkili alt sorgu kullanımı ekip içinde anlaşılırsa güvenli bir tercihtir.
  • NULL filtrelenmiş NOT IN: Alt sorgunun NULL içermediği garanti edilebiliyorsa veya bu garanti sorguda açıkça IS NOT NULL ile kuruluyorsa kullanılabilir.
  • LEFT JOIN ... IS NULL: Anti-join biçimi ekip için daha görünürse ve müşteri tarafındaki bilgilerle birlikte sorgu yapısında sipariş tarafını da göstermek anlamlıysa düşünülebilir.

Bu yaklaşımın bazı dikkat edilmesi gereken yönleri vardır:

  • Join koşulu yanlış kurulursa sonuç kümesi hatalı olur. Özellikle o.customer_id = c.customer_id gibi ilişkiyi gerçekten tanımlayan koşullar kullanılmalıdır.
  • Bir müşterinin birden fazla siparişi varsa normal eşleşme tarafında satır çoğalması görülebilir. Anti-join filtresiyle siparişi olmayan müşteriler seçilirken bu durum genellikle sonucu bozmaz; ancak ek koşullar veya farklı seçilen sütunlar dikkatle incelenmelidir.
  • Sonuç kümesinin boyutu, tabloların büyüklüğü ve ilgili index yapısı sorgu maliyetini etkileyebilir.
  • Optimizer’ın sorguyu nasıl çalıştıracağı; tablo istatistiklerine, index’lere, filtrelerin seçiciliğine ve kullanılan veritabanı sistemine bağlıdır. Bu nedenle yalnızca sorgu biçimine bakarak kesin bir performans sıralaması yapmak doğru değildir.

Pratik bir karar kuralı olarak, yalnızca “karşılığı var mı?” sorusunu soruyorsanız NOT EXISTS çoğu ekip için net bir anlatım sunar. İlişkiyi dış birleştirme biçiminde görmek istiyorsanız ve güvenilir bir sipariş kimliği üzerinden IS NULL kontrolü yapabiliyorsanız LEFT JOIN uygun olabilir.

Kendi NULL Senaryonu Tahmin Et: Mini Alıştırma ve Kontrol Listesi

Şimdi orders tablosuna şu satırın eklendiğini varsayın:

INSERT INTO orders (order_id, customer_id)
VALUES (106, NULL);

Bu satırın bir müşteriye bağlanmadığına dikkat edin. Sorguları çalıştırmadan önce üç yaklaşımın sonucunu tahmin edin:

  1. Hatalı NOT IN sorgusu hangi sonucu döndürür?
  2. Alt sorgusunda IS NOT NULL kullanan NOT IN sorgusu hangi müşterileri döndürür?
  3. NOT EXISTS yaklaşımı hangi müşterileri döndürür?

Beklenen cevap şöyledir:

  • Hatalı NOT IN sorgusu yine boş sonuç üretir.
  • NULL filtrelenmiş NOT IN sorgusu yine customer_id değeri 2 ve 4 olan müşterileri döndürür.
  • NOT EXISTS sorgusu da yine 2 ve 4 numaralı müşterileri döndürür.

Buradaki önemli nokta, ikinci bir NULL satırının sonucu ayrıca değiştirmemesidir. Sorunun kaynağı NULL sayısının kaç olduğu değil, alt sorgunun sonuç kümesinde en az bir NULL bulunmasıdır. NOT IN bu durumda listedeki her değerle ilgili kesin bir “eşit değil” sonucu üretemez ve koşul UNKNOWN durumuna düşebilir.

Hata teşhisi için kısa kontrol listesi

  • Önce alt sorguyu tek başına çalıştırın ve gerçekten hangi değerleri döndürdüğünü görün.
  • Alt sorguda NULL satırlarını bulmak için IS NULL kullanın.
  • NOT IN kullanıyorsanız alt sorguya IS NOT NULL koşulu eklenmesinin mantıksal olarak güvenli olup olmadığını değerlendirin.
  • Aynı ihtiyacı mümkünse NOT EXISTS ile karşılaştırın.
  • LEFT JOIN kullanıyorsanız NULL kontrolünü order_id gibi güvenilir birincil anahtar veya NULL olamayacak satır kimliği alanında yapın.

Sık Sorulan Sorular

NOT IN alt sorgusunda NULL varsa neden diğer değerler de sonuçtan çıkar?

Çünkü SQL, NULL ile yapılan karşılaştırmaları TRUE veya FALSE yerine UNKNOWN olarak değerlendirebilir. NOT IN tüm listedeki değerlerle “eşit değil” kontrolü yaptığı için listedeki tek bir NULL bile koşulun kesin olarak TRUE olmasını engelleyebilir. WHERE bölümü yalnızca TRUE olan satırları tuttuğundan sonuç boş kalabilir.

NOT IN ile NOT EXISTS arasındaki temel fark nedir?

NOT IN bir değerin bir listedeki değerlerin hiçbirine eşit olmamasını kontrol eder ve listedeki NULL değerlerinden etkilenebilir. NOT EXISTS ise dış tablodaki mevcut satır için eşleşen bir kayıt bulunup bulunmadığını kontrol eder. Bu nedenle alt sorgudaki ilişkisiz NULL değerleri, eşleşme kontrolünü aynı biçimde bozmaz.

NULL ile boş string veya 0 arasındaki fark nedir?

NULL, değerin bilinmediğini veya mevcut olmadığını ifade eder. Boş string '', uzunluğu sıfır olan gerçek bir metin değeridir; 0 ise gerçek bir sayısal değerdir. Bu üçü birbirine eşit değildir ve NULL kontrolü için = yerine IS NULL veya IS NOT NULL kullanılmalıdır.

LEFT JOIN ... WHERE IS NULL kullanırken hangi alanda NULL kontrolü yapılmalıdır?

Kontrol, eşleşen satırın kimliğini temsil eden ve normal koşullarda NULL olamayacak alanda yapılmalıdır. Bu nedenle çoğu durumda orders.order_id IS NULL uygundur. İsteğe bağlı bir sütunu kontrol etmek, sipariş gerçekten mevcut olsa bile o sütunun NULL olduğu kayıtları yanlışlıkla dışarıda bırakabilir.

NOT IN, NOT EXISTS ve LEFT JOIN ... IS NULL arasında seçim yaparken önce NULL ihtimalini, sonra join koşulunun doğruluğunu ve sorgunun ekip içindeki okunabilirliğini değerlendirin.

Bu içerik aradığın cevabı verdi mi?
Yanıtın, hangi yazıları geliştirmemiz gerektiğini anlamamıza yardımcı olur.
Bu içeriğin üretilmesinde yapay zeka araçlarından destek alınmıştır.

Bu konudan sonra ne okuyabilirsin?

Tüm yazılar

İlgili Eğitimler

Berk Keskin — Yazılım Geliştirici ve Eğitmen
Yazar

Berk Keskin Kimdir?

Yazılıma 12 yaşında başladı; bugün öğrencinin seviyesine ve hedefine göre şekillenen sürdürülebilir öğrenme sistemleri tasarlıyor. 500'den fazla kişiye ezber değil, düşünerek kod yazmayı öğretti — Berk Akademi'de izlemeye değil üretmeye dayalı öğrenme kültürünü o kuruyor.

WhatsApp Hemen Ara