---
title: 'Boş Değerler'
source: 'https://academia.sh/tr/kurslar/iliskisel-kuram/bos-degerler'
course: 'Veri Modelleme ve İlişkisel Kuram'
language: tr
updated: '2026-08-17T18:09:00+00:00'
license: 'CC BY-SA 4.0'
---

# Boş Değerler

Boş değerin bir değer olmaması, üç değerli mantığın doğruluk tablosu, süzgeçlerin ve NOT IN yazımının davranışı, tekillik kısıtının boş değere bakışı ve boş değerden kaçınma yolları.

Önceki derste iki kez "ya boştur" ifadesi geçti: yabancı anahtar boş olabilir, `SET NULL`
eylemi sütunu boşaltır. Boş değerin ne anlama geldiği ise tanımlanmadı. Bu dersin sorusu
şudur: boş değer nedir, onunla yapılan karşılaştırmalar ne döndürür, ve doğru–yanlış
ikilisine üçüncü bir sonuç eklenmesi sorgu yazımında hangi tuzakları açar?

## Boş Değer Bir Değer Değildir

**Boş değer** (null), bir sütunda değer bulunmadığını gösteren işarettir. Sıfır değildir,
boş dizgi değildir, "yok" adlı özel bir değer de değildir. Anlamı "bu satır için o bilgi
mevcut değildir" biçiminde okunur ve iki ayrı durumu aynı işaretle temsil eder:
bilinmeyen bilgi (üyenin telefon numarası vardır ama kayıtlı değildir) ve uygulanamayan
bilgi (ödünç işleminin iade tarihi henüz oluşmamıştır). Bu iki durumun aynı işareti
paylaşması, ilişkisel modele yöneltilen en eski eleştirilerden biridir.

Bir değer olmadığı için, boş değer bir değerle karşılaştırılamaz. Karşılaştırmanın sonucu
doğru da yanlış da değildir:

```sh
sqlite3 :memory: <<'SQL'
.headers on
.mode box
.nullvalue (bos)
SELECT NULL = NULL           AS esit_mi,
       NULL <> NULL          AS farkli_mi,
       NULL IS NULL          AS bos_mu,
       (NULL = NULL) IS NULL AS sonuc_bos_mu;
SQL
```

```
┌─────────┬───────────┬────────┬──────────────┐
│ esit_mi │ farkli_mi │ bos_mu │ sonuc_bos_mu │
├─────────┼───────────┼────────┼──────────────┤
│ (bos)   │ (bos)     │ 1      │ 1            │
└─────────┴───────────┴────────┴──────────────┘
```

`NULL = NULL` doğru değildir; `NULL <> NULL` de doğru değildir. İkisi de üçüncü bir
sonuç verir. Boş değeri sınamanın tek doğru yolu `IS NULL` ve `IS NOT NULL`
işleçleridir — bunlar karşılaştırma değil, durum sorgusudur ve her zaman doğru ya da
yanlış döndürür.

## Üçüncü Doğruluk Değeri

Karşılaştırmanın verdiği üçüncü sonucun adı **bilinmiyor** (unknown), sisteminin adı ise
**üç değerli mantıktır** (three-valued logic). `AND` ve `OR` işleçleri bu üçüncü değeri de
kapsayacak biçimde genişletilmiştir. Tabloyu ezberlemek gerekmez; hesaplatmak yeter:

```sh
sqlite3 :memory: <<'SQL'
.headers on
.mode box
.nullvalue (bos)
WITH d(ad, v) AS (VALUES ('dogru', 1), ('yanlis', 0), ('bilinmiyor', NULL))
SELECT a.ad AS sol, b.ad AS sag,
       a.v AND b.v AS ve, a.v OR b.v AS veya
FROM d a, d b;
SQL
```

```
┌────────────┬────────────┬───────┬───────┐
│    sol     │    sag     │  ve   │ veya  │
├────────────┼────────────┼───────┼───────┤
│ dogru      │ dogru      │ 1     │ 1     │
│ dogru      │ yanlis     │ 0     │ 1     │
│ dogru      │ bilinmiyor │ (bos) │ 1     │
│ yanlis     │ dogru      │ 0     │ 1     │
│ yanlis     │ yanlis     │ 0     │ 0     │
│ yanlis     │ bilinmiyor │ 0     │ (bos) │
│ bilinmiyor │ dogru      │ (bos) │ 1     │
│ bilinmiyor │ yanlis     │ 0     │ (bos) │
│ bilinmiyor │ bilinmiyor │ (bos) │ (bos) │
└────────────┴────────────┴───────┴───────┘
```

Tabloda okunacak kural şudur: sonucu belirleyen bir taraf varsa bilinmezlik yayılmaz.
`yanlis AND bilinmiyor` yanlıştır, çünkü bir taraf yanlışsa sonuç ne olursa olsun
yanlıştır. `dogru OR bilinmiyor` doğrudur, aynı gerekçeyle. Diğer bütün durumlarda
bilinmezlik sonuca taşınır. Bu, Programlama Temelleri kursundaki kısa devre
değerlendirmenin mantık düzeyindeki karşılığıdır.

## Süzgecin Böldüğü Küme

`WHERE` yalnızca **doğru** sonucu veren satırları geçirir; yanlış ile bilinmiyor birlikte
elenir. Bunun görünür sonucu, birbirinin değili sanılan iki koşulun tüm satırları
kapsamamasıdır:

```sh
sqlite3 :memory: <<'SQL'
.headers on
.mode box
CREATE TABLE odunc (odunc_no INTEGER PRIMARY KEY, uye_no INTEGER, iade_tarihi TEXT);
INSERT INTO odunc VALUES (1001, 41, '2025-03-16'), (1002, 52, NULL),
                         (1003, 41, '2025-03-19'), (1004, 41, NULL);
SELECT (SELECT COUNT(*) FROM odunc) AS toplam,
       (SELECT COUNT(*) FROM odunc WHERE iade_tarihi =  '2025-03-16') AS esit,
       (SELECT COUNT(*) FROM odunc WHERE iade_tarihi <> '2025-03-16') AS farkli,
       (SELECT COUNT(*) FROM odunc WHERE iade_tarihi IS NULL) AS bos;
SQL
```

```
┌────────┬──────┬────────┬─────┐
│ toplam │ esit │ farkli │ bos │
├────────┼──────┼────────┼─────┤
│ 4      │ 1    │ 1      │ 2   │
└────────┴──────┴────────┴─────┘
```

Dört satır vardır; "eşittir" bir satır, "eşit değildir" bir satır döndürür. Toplamları
dörde ulaşmaz, çünkü iki satır iki süzgeçten de geçmez. İki değerli mantıkta alışılmış
olan "koşul ya da değili tüm kümeyi kapsar" kuralı, boş değer bulunan bir sütunda
geçerli değildir. Kapsama isteniyorsa koşul açıkça yazılır.

## `NOT IN` Tuzağı

Aynı kuralın en pahalı sonucu alt sorgularda görülür. `x NOT IN (a, b, c)` yazımı,
`x <> a AND x <> b AND x <> c` ifadesine denktir. Listede tek bir boş değer bulunuyorsa o
karşılaştırma bilinmiyor döner, `AND` zinciri bilinmezliğe düşer ve **hiçbir satır**
geçmez:

```sh
sqlite3 :memory: <<'SQL'
.headers on
.mode box
CREATE TABLE uye  (uye_no INTEGER PRIMARY KEY, ad TEXT NOT NULL);
CREATE TABLE ceza (ceza_no INTEGER PRIMARY KEY, uye_no INTEGER);
INSERT INTO uye  VALUES (41, 'Ayşe Demir'), (52, 'Mert Kaya'), (63, 'Selin Öztürk');
INSERT INTO ceza VALUES (9001, 52), (9002, NULL);

SELECT 'NOT IN, alt sorgu ham' AS yazim, COUNT(*) AS donen_satir
  FROM uye WHERE uye_no NOT IN (SELECT uye_no FROM ceza)
UNION ALL
SELECT 'NOT IN, bos degerler elenmis', COUNT(*)
  FROM uye WHERE uye_no NOT IN (SELECT uye_no FROM ceza WHERE uye_no IS NOT NULL)
UNION ALL
SELECT 'NOT EXISTS', COUNT(*)
  FROM uye u WHERE NOT EXISTS (SELECT 1 FROM ceza c WHERE c.uye_no = u.uye_no);
SQL
```

```
┌──────────────────────────────┬─────────────┐
│            yazim             │ donen_satir │
├──────────────────────────────┼─────────────┤
│ NOT IN, alt sorgu ham        │ 0           │
│ NOT IN, bos degerler elenmis │ 2           │
│ NOT EXISTS                   │ 2           │
└──────────────────────────────┴─────────────┘
```

Doğru yanıt ikidir: cezası bulunmayan iki üye vardır. İlk yazım sıfır döndürür ve bunu
hata vermeden yapar — sorgu geçerlidir, sonuç sessizce yanlıştır. Bu, boş değerin en sık
karşılaşılan tuzağıdır ve iki savunması vardır: ya alt sorguda boş değerler elenir, ya da
`NOT EXISTS` yazımı seçilir. İkincisi tercih edilir, çünkü doğruluğu alt sorgunun içeriğine
bağlı değildir.

## Tekillik ve Boş Değer

Tekillik kısıtı da aynı mantığı izler. İki boş değer birbirine eşit sayılmadığı için,
tekil bir sütun birden çok boş değer taşıyabilir:

```sh
sqlite3 :memory: <<'SQL'
.headers on
.mode box
CREATE TABLE uye (
  uye_no INTEGER PRIMARY KEY,
  ad     TEXT NOT NULL,
  tc_no  TEXT UNIQUE
);
INSERT INTO uye VALUES (41, 'Ayşe Demir', NULL);
INSERT INTO uye VALUES (52, 'Mert Kaya', NULL);
INSERT INTO uye VALUES (63, 'Selin Öztürk', NULL);
SELECT COUNT(*) AS satir FROM uye;
SQL
```

```
┌───────┐
│ satir │
├───────┤
│ 3     │
└───────┘
```

Üç satır da geçmiştir. Bu davranış standarda uygundur, ancak **motora göre değişebilir**;
kimi sistemde tekil sütunda yalnız bir boş değere izin verilir. Bu belirsizliğin pratik
sonucu şudur: bir sütunun hem tekil hem zorunlu olmasını istiyorsanız `UNIQUE` yeterli
değildir, yanına `NOT NULL` yazılmalıdır. Tersi de doğrudur: tekillik kısıtı, boş
değerlerin sayısını sınırlamak için kullanılamaz.

## Toplama İşlevleri

Toplama işlevleri boş değerleri sayıma katmaz. `COUNT(*)` satır sayar, `COUNT(sutun)` o
sütunda değer bulunan satırları sayar; `SUM` ve `AVG` boş değerleri atlar:

```sh
sqlite3 :memory: <<'SQL'
.headers on
.mode box
.nullvalue (bos)
CREATE TABLE ceza (ceza_no INTEGER PRIMARY KEY, tutar INTEGER);
INSERT INTO ceza VALUES (9001, 30), (9002, NULL), (9003, 10);
SELECT COUNT(*) AS satir, COUNT(tutar) AS dolu_tutar,
       SUM(tutar) AS toplam, AVG(tutar) AS ortalama FROM ceza;
SQL
```

```
┌───────┬────────────┬────────┬──────────┐
│ satir │ dolu_tutar │ toplam │ ortalama │
├───────┼────────────┼────────┼──────────┤
│ 3     │ 2          │ 40     │ 20.0     │
└───────┴────────────┴────────┴──────────┘
```

Ortalama, üç satırın değil iki değerin ortalamasıdır. Boş değeri sıfır saymak isteniyorsa
bu açıkça yazılmalıdır; işlevin kendiliğinden yaptığı şey atlamaktır. Sıralamada boş
değerlerin başa mı sona mı geleceği ise standartta belirtilmemiştir ve **motora göre
değişir**; belirli bir yer isteniyorsa sıralama ifadesinde açıkça bildirilmelidir.

## Boş Değerden Kaçınmak

Boş değer bir araçtır, hedef değildir. Üç yaygın durumda gereksiz yere ortaya çıkar ve
üçünün de modelleme karşılığı vardır.

- **Çok değerli olgu için ayrılmış sütunlar.** `telefon_1`, `telefon_2`, `telefon_3`
  sütunlarının ikisi çoğu satırda boştur. Karşılığı, telefonları ayrı bir bağıntıya
  taşımaktır.
- **Yalnız bazı satırlar için anlamlı sütunlar.** Süreli üyeliğe özgü bir bitiş tarihi,
  süresiz üyelerde boş durur. Karşılığı, alt türü ayrı bir bağıntıda tutmaktır.
- **Henüz gerçekleşmemiş olay.** İade tarihinin boş olması, ödünç işleminin sürdüğü
  anlamına gelir. Bu, boş değerin yerinde kullanımıdır — olayın olmadığını bildiren
  başka bir işaret yoktur.

Genel ölçüt şudur: boş değer bir **durum** bildiriyorsa yerindedir; eksik modellemeyi
kapatıyorsa şema düzeltilmelidir.

## Özet

- Boş değer bir değer değildir; sıfırdan ve boş dizgiden ayrıdır ve yalnız `IS NULL` ile
  sınanır.
- Karşılaştırmalar üçüncü bir sonuç üretir; `WHERE` yalnız doğru olanı geçirir, bu yüzden
  bir koşul ile değili tüm satırları kapsamaz.
- `NOT IN` alt sorgusunda tek bir boş değer sonucu sessizce boşaltır; `NOT EXISTS` bu
  duyarlılığı taşımaz.
- Tekillik kısıtı boş değerleri birbirinden farklı sayar; zorunluluk isteniyorsa
  `NOT NULL` ayrıca yazılır.
- Toplama işlevleri boş değerleri atlar; ortalama, satır sayısına değil değer sayısına
  bölünür.

## Sonraki Adım

Bu ders bir sütunun boş olabilmesinin sonuçlarını gösterdi; sütunun **ne tuttuğu** ise
hâlâ belirsiz. Kurs boyunca tarihler metin olarak, tutarlar tam sayı olarak yazıldı ve bu
seçimler gerekçelendirilmedi. Sıradaki ders sayı, metin, tarih ve ikili tipleri ele alır;
para tutarının neden kayan noktalı sayıda tutulmadığını, metin karşılaştırmasının hangi
ayara bağlı olduğunu ve büyük ikili verinin veritabanında durup durmayacağını tartışır.
