NULL Handling: IS NULL, COALESCE, IFNULL
Giriş — NULL: SQL'in En Kafa Karıştıran Kavramı
SQL'de NULL, başlangıçta masum görünür ama aslında birçok insanı tuzağa düşüren, beklenmedik sonuçlara yol açan bir kavramdır. NULL, "boş" veya "sıfır" demek değildir. NULL, "bilinmeyen" veya "mevcut olmayan" demektir.
Bu fark büyüktür: bir müşterinin telefonunun "" (boş string) olması, "telefonu var ama numara girilmemiş" demektir. NULL olması ise "telefonu olup olmadığını bilmiyoruz" demektir.
🎯 Analoji: Arkadaşına "Ahmet kaç yaşında?" diye soruyorsun. Cevaplar: - 0 → "Ahmet yeni doğdu" (sıfır bir değerdir) - "" → "Ahmet'in yaşını yazmadım" (boş string bir değerdir) - NULL → "Bilmiyorum" (hiçbir değer yok, bilgi mevcut değil)
NULL Nedir, Ne Değildir?
-- NULL ≠ 0
SELECT NULL = 0; -- Sonuç: NULL (TRUE veya FALSE değil!)
-- NULL ≠ '' (boş string)
SELECT NULL = ''; -- Sonuç: NULL
-- NULL ≠ NULL
SELECT NULL = NULL; -- Sonuç: NULL (!!!)
-- İki "bilinmeyen" şeyin eşit olup olmadığını bilemezsinBu son satır çok kritiktir: NULL, kendisiyle bile eşit değildir.
Üç Değerli Mantık (Three-Valued Logic)
Normal programlama dillerinde TRUE ve FALSE vardır. SQL'de üçüncü bir değer daha var: UNKNOWN (NULL ile karşılaştırma sonucu).
| A | B | A = B | A AND B | A OR B |
|---|---|---|---|---|
| TRUE | TRUE | TRUE | TRUE | TRUE |
| TRUE | FALSE | FALSE | FALSE | TRUE |
| TRUE | NULL | NULL | NULL | TRUE |
| FALSE | NULL | NULL | FALSE | NULL |
| NULL | NULL | NULL | NULL | NULL |
WHERE sadece TRUE olan satırları döndürür. NULL ve FALSE olan satırlar filtrelenir.
IS NULL ve IS NOT NULL
NULL değerleri kontrol etmenin tek doğru yolu IS NULL ve IS NOT NULL kullanmaktır:
-- Telefonu olmayan (NULL) müşteriler
SELECT first_name, last_name, phone
FROM customers
WHERE phone IS NULL;
-- Telefonu olan müşteriler
SELECT first_name, last_name, phone
FROM customers
WHERE phone IS NOT NULL;❌ Yanlış Yol: = NULL
-- ❌ YANLIŞ — Hiçbir satır dönmez!
SELECT * FROM customers WHERE phone = NULL;
-- NULL = NULL → NULL (TRUE değil) → satır filtrelenir
-- ❌ YANLIŞ — Bu da çalışmaz
SELECT * FROM customers WHERE phone != NULL;
-- NULL != NULL → NULL → satır filtrelenir
-- ✅ DOĞRU
SELECT * FROM customers WHERE phone IS NULL;
SELECT * FROM customers WHERE phone IS NOT NULL;⚠️ Dikkat: Bu SQL'in en yaygın hatalarından biridir.
= NULLkullanmak asla işe yaramaz. Her zamanIS NULL/IS NOT NULLkullan.
NULL ve Aritmetik İşlemler
NULL ile yapılan herhangi bir matematiksel işlemin sonucu NULL'dur:
SELECT 5 + NULL; -- NULL
SELECT 100 * NULL; -- NULL
SELECT NULL / 0; -- NULL (sıfıra bölme hatası bile vermez!)
SELECT CONCAT('Merhaba ', NULL); -- NULL (MySQL'de!)Bu e-ticarette nasıl sorun yaratır?
-- Bazı ürünlerin indirim yüzdesi NULL ise:
SELECT product_name,
price,
discount_percent,
price * (1 - discount_percent / 100) AS discounted_price
FROM products;
-- discount_percent NULL olan ürünler için discounted_price de NULL olur!
-- Ama biz NULL indirimi "indirim yok" yani %0 olarak yorumlamak istiyoruzCOALESCE — NULL'u Alternatif Değerle Değiştir
COALESCE, parametre listesindeki ilk NULL olmayan değeri döndürür:
COALESCE(deger1, deger2, deger3, ...)
-- İlk NULL olmayan değeri döndürür-- İndirim NULL ise 0 kabul et
SELECT product_name,
price,
COALESCE(discount_percent, 0) AS discount_percent,
price * (1 - COALESCE(discount_percent, 0) / 100) AS discounted_price
FROM products;
-- Telefon NULL ise "Belirtilmemiş" yaz
SELECT first_name,
last_name,
COALESCE(phone, 'Belirtilmemiş') AS phone
FROM customers;Birden Fazla Fallback
COALESCE'ın asıl gücü birden fazla alternatif verebilmesidir:
-- İletişim bilgisi: önce telefon, yoksa e-posta, o da yoksa 'Bilgi yok'
SELECT first_name,
COALESCE(phone, email, 'Bilgi yok') AS contact_info
FROM customers;
-- Ürün açıklaması: önce kısa açıklama, yoksa tam açıklama, o da yoksa 'Açıklama yok'
SELECT product_name,
COALESCE(short_description, full_description, 'Açıklama yok') AS description
FROM products;COALESCE ile Toplama
-- Siparişlerin toplam tutarını hesapla (NULL siparişler 0 kabul et)
SELECT customer_id,
COALESCE(SUM(total_amount), 0) AS total_spent
FROM orders
GROUP BY customer_id;IFNULL — MySQL'e Özel NULL Değiştirme
IFNULL MySQL'e özgüdür ve sadece 2 parametre alır. COALESCE'ın basitleştirilmiş halidir:
IFNULL(deger, alternatif)
-- deger NULL ise alternatif'i döndürür-- Stok bilgisi NULL ise 0 göster
SELECT product_name,
IFNULL(stock_quantity, 0) AS stock
FROM products;
-- Şehir bilgisi NULL ise 'Bilinmiyor'
SELECT first_name,
IFNULL(city, 'Bilinmiyor') AS city
FROM customers;COALESCE vs IFNULL:
| Özellik | COALESCE | IFNULL |
|---|---|---|
| SQL standardı | ✅ Evet (ANSI SQL) | ❌ Hayır (MySQL'e özel) |
| Parametre sayısı | 2+ (sınırsız) | Tam olarak 2 |
| PostgreSQL desteği | ✅ | ❌ |
| Performans | Aynı | Aynı |
💡 İpucu: Taşınabilir (portable) kod yazmak istiyorsan
COALESCEkullan. MySQL'e özel bir projedeIFNULLde çalışır amaCOALESCEevrenseldir.
📝 PostgreSQL Notu: PostgreSQL'de
IFNULLyoktur amaCOALESCEdesteklenir. Ayrıca PostgreSQL'deNULLIFveCOALESCEyanındaIS DISTINCT FROMoperatörü çok kullanışlıdır.
NULLIF — İki Değer Eşitse NULL Döndür
NULLIF, iki değer eşitse NULL, eşit değilse ilk değeri döndürür:
NULLIF(deger1, deger2)
-- deger1 = deger2 ise → NULL
-- deger1 ≠ deger2 ise → deger1SELECT NULLIF(10, 10); -- NULL (eşit)
SELECT NULLIF(10, 20); -- 10 (eşit değil)
SELECT NULLIF('abc', ''); -- 'abc' (eşit değil)
SELECT NULLIF('', ''); -- NULL (eşit)Nerede kullanılır?
En yaygın kullanım: sıfıra bölme hatasını önleme:
-- ❌ Sıfıra bölme hatası riski
SELECT product_name,
total_revenue / total_orders AS avg_order_value
FROM product_stats;
-- total_orders = 0 ise hata veya sonsuz!
-- ✅ NULLIF ile güvenli bölme
SELECT product_name,
total_revenue / NULLIF(total_orders, 0) AS avg_order_value
FROM product_stats;
-- total_orders = 0 ise → NULLIF(0, 0) = NULL → bölüm = NULL (hata yok)Boş string'i NULL'a çevirme:
-- Kullanıcı formu boş gönderdi ama '' olarak kaydedildi
-- Bunu NULL olarak ele almak istiyorsak:
SELECT first_name,
NULLIF(phone, '') AS phone -- '' ise NULL olsun
FROM customers;NULL ve Aggregate Fonksiyonlar
Aggregate fonksiyonlar NULL'u farklı ele alır:
-- Örnek veri:
-- product_id | price | discount_percent
-- 1 | 100 | 10
-- 2 | 200 | NULL
-- 3 | 300 | 20
-- 4 | 400 | NULL
-- COUNT(*) — NULL dahil TÜM satırları sayar
SELECT COUNT(*) FROM products; -- 4
-- COUNT(sütun) — NULL olmayan değerleri sayar
SELECT COUNT(discount_percent) FROM products; -- 2 (NULL'lar sayılmaz!)
-- SUM — NULL'ları atlar
SELECT SUM(discount_percent) FROM products; -- 30 (10 + 20, NULL'lar atlanır)
-- AVG — NULL'ları atlar (ortalaması etkilenir!)
SELECT AVG(discount_percent) FROM products; -- 15 (30 / 2, 4 değil!)
-- ⚠️ NULL olan 2 satır hesaba katılmadı!
-- NULL'ları 0 sayarak ortalama almak:
SELECT AVG(COALESCE(discount_percent, 0)) FROM products; -- 7.5 (30 / 4)⚠️ Dikkat:
AVG()NULL'ları atlar, dahil etmez. Eğer NULL'ları 0 olarak dahil etmek istiyorsanCOALESCEkullan. Bu fark özellikle puan ortalamalarında ve yüzde hesaplamalarında büyük anlam farkı yaratır.
NULL ve ORDER BY
-- NULL değerler sıralamada nereye düşer?
SELECT first_name, phone
FROM customers
ORDER BY phone ASC;
-- MySQL'de NULL'lar EN BAŞTA (en küçük değer muamelesi)
SELECT first_name, phone
FROM customers
ORDER BY phone DESC;
-- MySQL'de NULL'lar EN SONDANULL'ları sona göndermek (ASC sıralamada):
-- NULL'ları sona at
SELECT first_name, phone
FROM customers
ORDER BY phone IS NULL, phone ASC;
-- phone IS NULL → 0 (var) veya 1 (NULL) — önce 0'lar gelir📝 PostgreSQL Notu: PostgreSQL'de
NULLS FIRST/NULLS LASTdoğrudan desteklenir: ``sql ORDER BY phone ASC NULLS LAST;``
NULL-Safe Equality Operatörü: <=>
MySQL'de <=> operatörü NULL-safe eşitlik kontrolü yapar:
-- Normal = operatörü NULL ile çalışmaz
SELECT NULL = NULL; -- NULL
SELECT 1 = NULL; -- NULL
-- <=> NULL ile güvenli çalışır
SELECT NULL <=> NULL; -- 1 (TRUE)
SELECT 1 <=> NULL; -- 0 (FALSE)
SELECT 1 <=> 1; -- 1 (TRUE)-- phone NULL olan müşterileri bul (IS NULL alternatifi)
SELECT * FROM customers WHERE phone <=> NULL;
-- İki sütun karşılaştırması (NULL olabilir)
SELECT * FROM employees
WHERE manager_id <=> department_id; -- İkisi de NULL ise bile eşleşirGerçek Dünya Örneği — NULL-Aware E-Ticaret Raporları
-- 1. Müşteri profil doluluk raporu
SELECT
customer_id,
first_name,
last_name,
CASE
WHEN phone IS NOT NULL AND city IS NOT NULL THEN 'Tam'
WHEN phone IS NOT NULL OR city IS NOT NULL THEN 'Kısmi'
ELSE 'Eksik'
END AS profil_durumu,
COALESCE(phone, 'Yok') AS telefon,
COALESCE(city, 'Yok') AS sehir
FROM customers;
-- 2. Ürün indirim raporu (NULL = indirim yok)
SELECT
product_name,
price AS normal_fiyat,
COALESCE(discount_percent, 0) AS indirim_yuzdesi,
price * (1 - COALESCE(discount_percent, 0) / 100) AS indirimli_fiyat,
CASE
WHEN discount_percent IS NULL THEN 'İndirim yok'
WHEN discount_percent >= 20 THEN 'Büyük indirim'
WHEN discount_percent >= 10 THEN 'Orta indirim'
ELSE 'Küçük indirim'
END AS indirim_durumu
FROM products
WHERE is_active = TRUE;
-- 3. Sipariş özetinde NULL handling
SELECT
c.first_name,
c.last_name,
COUNT(o.order_id) AS siparis_sayisi,
COALESCE(SUM(o.total_amount), 0) AS toplam_harcama,
COALESCE(AVG(o.total_amount), 0) AS ortalama_siparis,
COALESCE(MAX(o.order_date), 'Sipariş yok') AS son_siparis
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id
GROUP BY c.customer_id, c.first_name, c.last_name;Sıkça Yapılan Hatalar
`= NULL` kullanmak: En yaygın NULL hatası.
WHERE phone = NULLasla çalışmaz.WHERE phone IS NULLkullan.NULL'un aritmetikte bulaşıcılığını unutmak:
5 + NULL = NULL. Hesaplamalarda COALESCE ile NULL'ları temizle.`COUNT(*)` ile `COUNT(sütun)` farkını bilmemek:
COUNT(*)tüm satırları,COUNT(sütun)sadece NULL olmayan değerleri sayar.`AVG()`'ın NULL'ları atlamasını bilmemek: 10 satırda 3'ü NULL ise ortalama 7 satır üzerinden hesaplanır, 10 değil. NULL'ları 0 saymak istiyorsan
AVG(COALESCE(sütun, 0))kullan.NOT IN ile NULL sorunu:
WHERE id NOT IN (SELECT col FROM table)— subquery NULL döndürürse hiçbir satır dönmez.CONCAT ile NULL kaybı: MySQL'de
CONCAT('Merhaba ', NULL)= NULL. CONCAT_WS veya COALESCE kullan:CONCAT('Merhaba ', COALESCE(name, 'Anonim')).
Özet
NULL "bilinmeyen" veya "mevcut değil" anlamına gelir — 0 veya boş string değildir
NULL ile
=karşılaştırması çalışmaz —IS NULL/IS NOT NULLkullanNULL ile yapılan her aritmetik işlem NULL döndürür
COALESCE(val1, val2, ...)ilk NULL olmayan değeri döndürür — evrensel çözümIFNULL(val, alt)MySQL'e özel, 2 parametreli COALESCENULLIF(val1, val2)iki değer eşitse NULL döndürür — sıfıra bölme korumasıAggregate fonksiyonlar NULL'ları atlar — özellikle
AVG()tuzağına dikkat<=>MySQL'de NULL-safe eşitlik operatörüdürGerçek uygulamalarda her yerde NULL olabilirliğini düşün ve COALESCE kullan
AI Asistan
Sorularını yanıtlamaya hazır