Share

Postgresql veritabanlarının NULL kayıtlardaki davranışı

Veritabanı yönetim sistemlerinde NULL, çoğu zaman yanlış anlaşılan ve beklenmedik sonuçlara yol açabilen özel bir kavramdır.

PostgreSQL’de NULL değeri, bir verinin atanmadığını veya mevcut olmadığını temsil eder. Kafa karıştırıcı olan nokta, NULL değerinin sıfır (0) veya boş bir metin (”) ile aynı şey olmamasıdır.

SQL standartlarına göre NULL hiçbir şeye eşit değildir, kendisine bile. Bu nedenle klasik eşittir (=) operatörüyle sorgulama yapamazsınız.

  • Yanlış: SELECT * FROM tablo WHERE kolon = NULL; (Hiçbir sonuç dönmez)
  • Doğru: SELECT * FROM tablo WHERE kolon IS NULL;

PostgreSQL sorguları değerlendirirken sadece TRUE veya FALSE değil, aynı zamanda UNKNOWN sonucunu da kullanır. Bir NULL değerini herhangi bir sayıyla toplarsanız veya karşılaştırırsanız, sonuç her zaman NULL (UNKNOWN) olur.

Postgresql veritabanlarında NULL olan kayıtlar için diğer veritabanlarına göre davranışı biraz farklıdır.

NULL Nedir? Ne Değildir?

Değer Anlamı NULL ile Eşit mi?
0 (sayı) Sıfır değeri Hayır
” (boş string) Uzunluğu 0 olan karakter dizisi Hayır
false (boolean) Mantıksal yanlış Hayır
NULL Bilinmiyor / Tanımsız Hayır (kendisiyle bile eşit değildir!)

PostgreSQL’de NULL = NULL ifadesinin sonucu NULL (bilinmiyor) olarak değerlendirilir, true değil. Bu nedenle eşitlik kontrolü için = yerine IS NULL operatörü kullanılmalıdır.

-- Yanlış kullanım:

SELECT * FROM users WHERE age = NULL;   -- Hiç sonuç döndürmez

-- Doğru kullanım:

SELECT * FROM users WHERE age IS NULL;

Karşılaştırma Operatörleri ve NULL

PostgreSQL, üç değerli mantık (three-valued logic) kullanır: TRUE, FALSE, UNKNOWN (NULL). Bir karşılaştırmada taraflardan biri NULL ise sonuç her zaman UNKNOWN olur.

İfade Sonuç
NULL = NULL NULL
NULL <> NULL NULL
NULL > 10 NULL
NULL = ” NULL
NULL IS NULL TRUE
NULL IS NOT NULL FALSE

 

-- Örnek tablo

CREATE TABLE employees (

    id SERIAL PRIMARY KEY,

    name TEXT,

    bonus INTEGER

);




INSERT INTO employees (name, bonus) VALUES

    ('Ahmet', 1000),

    ('Mehmet', NULL),

    ('Zeynep', 0);




-- Sorgular ve sonuçları:

SELECT * FROM employees WHERE bonus = NULL;    -- 0 satır

SELECT * FROM employees WHERE bonus IS NULL;   -- Mehmet gelir

SELECT * FROM employees WHERE bonus = 0;       -- Zeynep gelir

 

NULL ile Mantıksal İşlemler (AND / OR)

PostgreSQL’de mantıksal işlemlerde NULL, UNKNOWN olarak ele alınır:

A B A AND B A OR B NOT A
TRUE NULL UNKNOWN TRUE FALSE
FALSE NULL FALSE UNKNOWN TRUE
NULL NULL UNKNOWN UNKNOWN UNKNOWN

 

-- WHERE koşullarında UNKNOWN, FALSE gibi davranır (satırı elemez)

SELECT * FROM employees WHERE bonus = 1000 OR bonus = NULL;

-- Sadece bonus=1000 olan Ahmet gelir, çünkü bonus=NULL olan koşul UNKNOWN verir.

NULL ve Aggregate Fonksiyonları

PostgreSQL, toplamsal (aggregate) fonksiyonlarda NULL değerleri yok sayar:

Fonksiyon Davranış
COUNT(*) NULL’ları sayar (tüm satırları sayar)
COUNT(column) NULL’ları saymaz
SUM(column) NULL’ları yok sayar, toplama katmaz
AVG(column) NULL’ları yok sayar, sadece NULL olmayanların ortalamasını alır
MAX(column) / MIN(column) NULL’ları yok sayar

 

SELECT

    COUNT(*) AS total_satir,           -- 3

    COUNT(bonus) AS bonus_olmayan,     -- 2 (Mehmet sayılmaz)

    SUM(bonus) AS toplam_bonus,        -- 1000

    AVG(bonus) AS ortalama_bonus       -- 500 (1000/2, 3'e bölünmez!)

FROM employees;

AVG beklenmedik sonuç verebilir. Yukarıdaki örnekte ortalama (1000+0)/2 = 500 olarak hesaplanır, (1000+0+NULL)/3 = 333 değil.

NULL ve DISTINCT / GROUP BY

  • DISTINCT: Tüm NULL değerleri tek bir grup olarak değerlendirir.
  • GROUP BY: NULL değerler kendi grubunda toplanır.

 

INSERT INTO employees (name, bonus) VALUES ('Ayşe', NULL);



SELECT bonus, COUNT(*) FROM employees GROUP BY bonus;



-- Sonuç:

-- bonus  | count

-- -------+-------

-- 1000   |   1

-- 0      |   1

-- NULL   |   2      (Mehmet ve Ayşe)

 

NULL ve Eşitsizlik ifadesi

PostgreSQL’de varsayılan olarak bir sorguda eşitsizlik operatörü kullanıldığında NULL değerler gelmez. Aşağıdaki gibi bir sorguda bonus değeri 0 (sıfır) olmayanlar eşitsizliğinde , NULL  olan kayıtlar gelmeyecektir.

SELECT name, bonus FROM employees where bonus<>0;

-- Ahmet (1000)

NULL olan kayıtların da eşitsizlik operatöründe gelmesini istiyorsak ilave koşul belirtmek gerekecektir.

SELECT name, bonus FROM employees where bonus<>0 or bonus IS NULL;

 


NULL ve Sıralama (ORDER BY)

PostgreSQL’de varsayılan sıralamada NULL değerler en büyük kabul edilir (ASC’de sonda, DESC’de başta gelir). Bu davranış NULLS FIRST ve NULLS LAST ile değiştirilebilir.

SELECT name, bonus FROM employees ORDER BY bonus ASC;

-- Zeynep (0), Ahmet (1000), Mehmet (NULL), Ayşe (NULL)




SELECT name, bonus FROM employees ORDER BY bonus ASC NULLS FIRST;

-- Mehmet (NULL), Ayşe (NULL), Zeynep (0), Ahmet (1000)




SELECT name, bonus FROM employees ORDER BY bonus DESC NULLS LAST;

-- Ahmet (1000), Zeynep (0), Mehmet (NULL), Ayşe (NULL)

 

NULL ve Benzersiz Kısıtlamalar (UNIQUE)

PostgreSQL’de UNIQUE kısıtlaması, NULL değerleri birbirinden farklı kabul etmez mi? Hayır, tam tersi:

  • Bir sütun UNIQUE ise, birden fazla NULL değer girebilir.
  • Çünkü PostgreSQL, NULL = NULL eşitliğini sağlamadığı için her NULL’u farklı bir değer olarak görür.
CREATE TABLE test_unique (id INT UNIQUE);

INSERT INTO test_unique VALUES (NULL);  -- Başarılı

INSERT INTO test_unique VALUES (NULL);  -- Başarılı (2. NULL)

-- İki NULL değer aynı anda bulunabilir.

İstisna: PRIMARY KEY sütunu NULL olamaz (hem NOT NULL hem UNIQUE içerir).

NULL ile String Birleştirme (Concatenation)

PostgreSQL’de || operatörü ile string birleştirmede eğer operandlardan biri NULL ise sonuç NULL olur.

 

SELECT 'Hello' || NULL || 'World';  -- NULL

SELECT CONCAT('Hello', NULL, 'World');  -- 'HelloWorld' (CONCAT NULL'ı yok sayar)

Öneri: NULL değerleri yönetmek için COALESCE veya CONCAT kullanın.

NULL Yönetimi için Pratik Fonksiyonlar

Fonksiyon Açıklama Örnek
COALESCE(value, default) İlk NULL olmayan değeri döndürür COALESCE(bonus, 0)
NULLIF(a, b) a = b ise NULL, değilse a döndürür NULLIF(division, 0)
ISNULL() (SQL Server) PostgreSQL’de yok, COALESCE kullanın
CASE Koşullu NULL yönetimi CASE WHEN bonus IS NULL THEN 0 ELSE bonus END

 

-- Kullanıcı adı ve bonusu göster, NULL ise 0 göster

SELECT name, COALESCE(bonus, 0) AS bonus_amount FROM employees;

 

 

En Çok Yapılan Hatalar ve Çözümleri

Hatalı Kullanım Sonuç Doğru Kullanım
column = NULL Her zaman FALSE column IS NULL
column <> NULL Her zaman FALSE column IS NOT NULL
COUNT(column) NULL’ları saymaz COUNT(*) veya SUM(CASE WHEN column IS NULL THEN 1 ELSE 0 END)
column IN (1,2,NULL) NULL içeren IN ifadesi UNKNOWN döndürür column IN (1,2) OR column IS NULL
NOT IN (SELECT … WHERE col IS NULL) Hiç satır döndürmeyebilir NOT EXISTS kullanın

 

NOT IN alt sorgusu NULL içeriyorsa, ana sorgu hiçbir satır döndürmez!

 

-- YANLIŞ:

SELECT * FROM employees WHERE bonus NOT IN (1000, NULL);  -- 0 satır




-- DOĞRU:

SELECT * FROM employees WHERE bonus NOT IN (1000) OR bonus IS NULL;

-- veya

SELECT * FROM employees WHERE NOT EXISTS (

    SELECT 1 FROM (VALUES (1000), (NULL)) AS t(val) WHERE t.val = employees.bonus

);

 

Performans ve İndeksleme

PostgreSQL’de NULL değerler B-tree indekslerinde yer alır. Ancak IS NULL sorguları, indeks kullanımı açısından özel durum gerektirebilir.

 

-- Bu sorgu indeks kullanabilir:

CREATE INDEX idx_bonus ON employees(bonus);

SELECT * FROM employees WHERE bonus IS NULL;  -- İndeksi kullanır (PG 9.2+)




-- Ancak kısmi indeks daha verimli olabilir:

CREATE INDEX idx_bonus_null ON employees(bonus) WHERE bonus IS NULL;

 

Öneriler :

  1. NULL’u asla sıfır veya boş string ile karıştırmayın.
  2. Eşitlik kontrolünde daima IS NULL / IS NOT NULL kullanın.
  3. Aggregate fonksiyonlarının NULL’ları yok saydığını unutmayın.
  4. NOT IN kullanırken alt sorguda NULL olabileceğini göz önünde bulundurun.
  5. Sıralama davranışını NULLS FIRST/LAST ile netleştirin.
  6. COALESCE ile NULL’ları varsayılan değerlere dönüştürün.
  7. Veritabanı tasarımında mümkünse NOT NULL kısıtlaması kullanın.
  8. <> operatörüyle birlikte “or is null” koşulunu da ekleyin.

Loading

You may also like