---
title: 'Bütünlük Kısıtları'
source: 'https://academia.sh/tr/kurslar/iliskisel-kuram/butunluk-kisitlari'
course: 'Veri Modelleme ve İlişkisel Kuram'
language: tr
updated: '2026-08-17T18:09:00+00:00'
license: 'CC BY-SA 4.0'
---

# Bütünlük Kısıtları

Alan, varlık ve başvuru bütünlüğünün tanımı; yabancı anahtarın silme ve güncelleme eylemleri; kısıt denetiminin zamanlaması ve kısıtın şemaya yazılmasının gerekçesi.

Önceki ders bir yabancı anahtar ihlalini reddetti ama arkasındaki kuralı adlandırmadı.
Bu dersin sorusu şudur: veritabanının her an sağlaması gereken kurallar nelerdir, bu
kurallar şemada nasıl yazılır, ve kuralı bozacak bir silme geldiğinde sistemin
seçebileceği davranışlar hangileridir?

Kısıtlar üç katmanda toplanır. **Alan bütünlüğü** (domain integrity) bir sütuna hangi
değerlerin yazılabileceğini söyler — tip, `NOT NULL` ve `CHECK` bunun araçlarıdır ve
önceki derste görüldü. **Varlık bütünlüğü** (entity integrity) her satırın kimliğinin
belirli olmasını ister. **Başvuru bütünlüğü** (referential integrity) bir bağıntıdan
diğerine yapılan başvurunun boşa düşmemesini ister. Dördüncü bir katman, alana özgü iş
kurallarıdır; bunlar da mümkün olduğunca şemaya yazılır.

## Varlık Bütünlüğü

Kural tek cümledir: **birincil anahtarı oluşturan hiçbir sütun boş değer alamaz.**
Gerekçesi doğrudan anahtarın tanımından gelir. Anahtarın işi satırı ayırt etmektir; boş
değer ise "bilinmiyor" demektir. Kimliği bilinmeyen bir satır, kendisine başvurulamayan
bir satırdır.

Bu kuralın standartta yazılı olması, her motorun onu aynı sıkılıkta uyguladığı anlamına
gelmez:

```sh
sqlite3 :memory: <<'SQL'
.headers on
.mode box
CREATE TABLE sube (sube_kodu TEXT PRIMARY KEY, ad TEXT NOT NULL);
INSERT INTO sube VALUES (NULL, 'Adsız Şube');
SELECT COUNT(*) AS satir FROM sube;
SQL
```

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

Birincil anahtarı boş olan bir satır tabloya girdi. **Bu davranış motora göre değişir**;
kimi motor aynı deyimi reddeder. Taşınabilir ve niyeti açık şema, kuralı kendi yazar:

```sh
sqlite3 :memory: <<'SQL'
CREATE TABLE sube (sube_kodu TEXT PRIMARY KEY NOT NULL, ad TEXT NOT NULL);
INSERT INTO sube VALUES (NULL, 'Adsız Şube');
SQL
```

```
Runtime error near line 2: NOT NULL constraint failed: sube.sube_kodu (19)
```

Buradan çıkan genel ilke, kursun tekrar eden temalarından biridir: bir kuralın motorda
zaten var olduğunu varsaymak yerine şemada açıkça yazmak, hem taşınabilirliği hem
okunabilirliği artırır.

## Başvuru Bütünlüğü

Kural şudur: bir yabancı anahtarın değeri ya boştur, ya da başvurduğu bağıntıda o değere
sahip bir satır **vardır**. Üçüncü bir olasılık yoktur; hedefi bulunmayan satıra **yetim
kayıt** (orphan record) denir.

Bu kuralın uygulanıp uygulanmadığı da motora göre değişir. Burada kullanılan komut satırı
aracında denetim varsayılan olarak kapalıdır ve oturum başına açılması gerekir:

```sh
sqlite3 :memory: <<'SQL'
.headers on
.mode box
PRAGMA foreign_keys;
CREATE TABLE uye (uye_no INTEGER PRIMARY KEY, ad TEXT NOT NULL);
CREATE TABLE odunc (
  odunc_no INTEGER PRIMARY KEY,
  uye_no   INTEGER NOT NULL REFERENCES uye (uye_no)
);
INSERT INTO odunc VALUES (1001, 77);
SELECT COUNT(*) AS yetim_kayit FROM odunc;
SQL
```

```
┌──────────────┐
│ foreign_keys │
├──────────────┤
│ 0            │
└──────────────┘
┌─────────────┐
│ yetim_kayit │
├─────────────┤
│ 1           │
└─────────────┘
```

Şemada `REFERENCES` yazılıdır, üye tablosu boştur, buna rağmen ödünç kaydı girmiştir.
Denetim kapalı olduğu için bildirim yalnızca belgeleme değeri taşımıştır. Bu dersin geri
kalanındaki bloklar denetimi açan satırla başlar.

## Silme ve Güncelleme Eylemleri

Başvuru bütünlüğü bozulabilecek iki an vardır: başvurulan satır silindiğinde ve başvurulan
anahtar değeri güncellendiğinde. Şema, bu iki an için bir davranış seçer.

- **`NO ACTION` / `RESTRICT`** — işlem reddedilir. Standarttaki varsayılan davranıştır;
  ikisi arasındaki fark denetimin zamanlamasındadır.
- **`CASCADE`** — silme ya da güncelleme, başvuran satırlara yayılır.
- **`SET NULL`** — başvuran satırın yabancı anahtarı boşaltılır; sütunun boş değer
  kabul etmesi gerekir.
- **`SET DEFAULT`** — başvuran satırın yabancı anahtarı sütunun öntanımlı değerine
  çekilir; o değerin hedefte bulunması gerekir.

Seçim keyfî değildir, alanın anlamını izler. Üye silindiğinde onun ceza kayıtlarının
kalması anlamsızdır — bunlar üyeye bağımlı, kendi başına var olamayan kayıtlardır, yani
`CASCADE`. Şube kapandığında üyenin kaydı silinmemelidir; üye şubesiz kalır, yani
`SET NULL`. Üyeye ait ödünç geçmişi ise silinmemelidir — geçmiş kayıt bir olgudur — bu
yüzden silme reddedilir.

```sh
sqlite3 :memory: <<'SQL'
.headers on
.mode box
.nullvalue (bos)
PRAGMA foreign_keys = ON;
CREATE TABLE sube (sube_kodu TEXT PRIMARY KEY NOT NULL, ad TEXT NOT NULL);
CREATE TABLE uye (
  uye_no    INTEGER PRIMARY KEY,
  ad        TEXT NOT NULL,
  sube_kodu TEXT REFERENCES sube (sube_kodu) ON DELETE SET NULL
);
CREATE TABLE ceza (
  ceza_no INTEGER PRIMARY KEY,
  uye_no  INTEGER NOT NULL REFERENCES uye (uye_no) ON DELETE CASCADE,
  tutar   INTEGER NOT NULL
);
INSERT INTO sube VALUES ('MRK', 'Merkez'), ('BHC', 'Bahçelievler');
INSERT INTO uye VALUES (41, 'Ayşe Demir', 'MRK'), (52, 'Mert Kaya', 'BHC');
INSERT INTO ceza VALUES (9001, 52, 30), (9002, 52, 15);
DELETE FROM uye  WHERE uye_no = 52;
DELETE FROM sube WHERE sube_kodu = 'MRK';
SELECT (SELECT COUNT(*) FROM uye)  AS uye_satiri,
       (SELECT COUNT(*) FROM ceza) AS ceza_satiri,
       (SELECT sube_kodu FROM uye WHERE uye_no = 41) AS uye41_sube;
SQL
```

```
┌────────────┬─────────────┬────────────┐
│ uye_satiri │ ceza_satiri │ uye41_sube │
├────────────┼─────────────┼────────────┤
│ 1          │ 0           │ (bos)      │
└────────────┴─────────────┴────────────┘
```

Tek bir üye silindi ve ona bağlı iki ceza kaydı da gitti; şube silindi ve ona bağlı üye
şubesiz kaldı. `.nullvalue` ayarı, boş değeri çıktıda görünür kılmak içindir — ayar
verilmediğinde boş değer ile boş dizgi ekranda ayırt edilemez.

Öntanımlı davranış ise reddetmektir:

```sh
sqlite3 :memory: <<'SQL'
PRAGMA foreign_keys = ON;
CREATE TABLE uye (uye_no INTEGER PRIMARY KEY, ad TEXT NOT NULL);
CREATE TABLE odunc (
  odunc_no INTEGER PRIMARY KEY,
  uye_no   INTEGER NOT NULL REFERENCES uye (uye_no)
);
INSERT INTO uye VALUES (41, 'Ayşe Demir');
INSERT INTO odunc VALUES (1001, 41);
DELETE FROM uye WHERE uye_no = 41;
SQL
```

```
Runtime error near line 9: FOREIGN KEY constraint failed (19)
```

`CASCADE` seçiminde dikkatli olmak gerekir: yayılma zincirlenir. Üyeyi silen bir deyim,
ona bağlı ceza kayıtlarını, onlara bağlı ödeme kayıtlarını ve bu zincirin devamını da
siler. Silinen satır sayısı, deyimi yazanın gördüğünden çok daha büyük olabilir.

## Kısıt Ne Zaman Denetlenir

Kısıtlar öntanımlı olarak her deyimin sonunda denetlenir. Bu, bazı doğru durumların
geçici olarak kurulamamasına yol açar. İki bağıntı birbirine karşılıklı başvuruyorsa —
her şubenin bir yöneticisi vardır ve her yönetici bir şubede çalışır — hangisi önce
eklenirse eklensin, ekleme anında karşı taraf henüz yoktur.

Çözüm, denetimi işlemin sonuna ertelemektir; buna **ertelenmiş kısıt** (deferred
constraint) denir. Ertelenmiş denetimde ara durumlar kuralı bozabilir, yeter ki işlem
tamamlandığında kural sağlansın. **Bu yeteneğin bulunup bulunmadığı ve nasıl bildirildiği
motora göre değişir**; bulunmayan motorlarda karşılıklı başvurunun bir ucunun boş değer
kabul etmesi ve iki adımda doldurulması gerekir.

## Kısıtı Nereye Yazmalı

Her kural şemaya sığmaz. "Bir üye aynı anda en çok beş nüsha ödünç alabilir" kuralı, tek
satıra bakarak denetlenemez; sayım gerektirir. Böyle kurallar ya bir tetikleyiciyle ya da
uygulama katmanında yazılır.

Ölçüt şudur: kural veriye erişen **bütün** yollar için geçerliyse ve tek bir satır ya da
satır kümesi üzerinden ifade edilebiliyorsa şemaya yazılır. Şemadaki kısıt, hangi
programın yazdığından, hangi dilde yazıldığından ve veriye elle mi yoksa toplu göçle mi
dokunulduğundan bağımsız olarak uygulanır. Uygulama katmanındaki denetim yalnızca o
uygulamadan geçen yazmaları kapsar; ikinci bir servis, bir bakım betiği ya da elle
çalıştırılan bir deyim onu atlar.

Kısıtın ikinci işlevi belgelemedir. Şemayı okuyan biri, `ON DELETE CASCADE` yazan bir
satırdan ceza kaydının üyeye bağımlı olduğunu okur. Aynı bilgi uygulama kodunda dağınık
biçimde durduğunda okunmaz.

## Özet

- Varlık bütünlüğü birincil anahtarın boş değer alamamasıdır; kimliği belirsiz satıra
  başvurulamaz.
- Başvuru bütünlüğü, yabancı anahtarın ya boş olmasını ya da hedefte karşılığı bulunmasını
  ister; ihlali yetim kayıt üretir.
- Motorun bir kuralı öntanımlı olarak uyguladığını varsaymak yerine kısıtı şemada açıkça
  yazmak taşınabilirliği ve okunabilirliği artırır.
- Silme ve güncelleme eylemleri — reddetme, yayma, boşaltma, öntanımlıya çekme — alanın
  anlamına göre seçilir; yayma zincirlenerek beklenenden çok satır siler.
- Bütün yazma yollarını bağlayan ve satır düzeyinde ifade edilebilen kurallar şemaya,
  sayım ya da geçmiş gerektirenler uygulama katmanına yazılır.

## Sonraki Adım

Bu derste iki kez "ya boştur" ifadesi geçti: yabancı anahtar boş olabilir, `SET NULL`
sütunu boşaltır. Boş değerin ne anlama geldiği ise tanımlanmadı. Sıradaki ders, boş
değerin bir değer olmadığını, karşılaştırmaların onunla ne yaptığını ve doğru–yanlış
ikilisine üçüncü bir sonucun eklenmesinin sorgu yazımında hangi tuzakları açtığını gösterir.
