---
title: 'Güncelleme ve Silme'
source: 'https://academia.sh/tr/kurslar/sql-temelleri/guncelleme-ve-silme'
course: 'SQL Temelleri'
language: tr
updated: '2026-08-17T18:09:02+00:00'
license: 'CC BY-SA 4.0'
---

# Güncelleme ve Silme

UPDATE ve DELETE deyimlerinin yapısı, koşul cümlesi unutulduğunda ne olduğu, etkilenen satır sayısının okunması, işlem açıp geri alma alışkanlığı ve silmenin bağlı satırlara etkisi.

Veri tabloya girdi. Sıradaki iki deyim onu değiştirir ve siler. Sözdizimleri kursun en
kısa deyimleri arasındadır; tehlikeleri de tam olarak buradan gelir. `WHERE` cümlesi
isteğe bağlıdır — yani koşulu unutulmuş bir güncelleme sözdizimsel olarak kusursuzdur,
motor tarafından uyarısız kabul edilir ve tablodaki **her** satırı değiştirir.

Bu dersin bütün örnekleri `:memory:` veritabanında çalışır: bellekte kurulan, komut
bitince yok olan geçici bir veritabanı. Yıkıcı bir deyimin ne yaptığını görmenin yolu onu
çalıştırmaktır, ancak çalıştırılacağı yer gerçek veri değildir.

## Koşullu Güncelleme

`UPDATE` deyimi üç parçadan oluşur: hangi tablo, hangi sütunlara hangi değerler, hangi
satırlar. Üçüncü parça yazılmazsa "hangi satırlar" sorusunun yanıtı "hepsi" olur.

```sh
sqlite3 :memory: <<'SQL'
.headers on
.mode column
CREATE TABLE uye (
  uye_id INTEGER PRIMARY KEY,
  ad     TEXT NOT NULL,
  soyad  TEXT NOT NULL,
  durum  TEXT NOT NULL DEFAULT 'etkin'
           CHECK (durum IN ('etkin', 'askida', 'kapali'))
);
INSERT INTO uye VALUES (1,'Ayşe','Demir','etkin'),(2,'Mehmet','Kaya','etkin'),
                       (3,'Zeynep','Arslan','askida'),(4,'Emre','Yıldız','etkin');

SELECT uye_id, ad, soyad FROM uye WHERE uye_id = 2;

UPDATE uye SET durum = 'askida' WHERE uye_id = 2;
SELECT changes() AS etkilenen;

SELECT * FROM uye;
SQL
```

```
uye_id  ad      soyad
------  ------  -----
2       Mehmet  Kaya 
etkilenen
---------
1        
uye_id  ad      soyad   durum 
------  ------  ------  ------
1       Ayşe    Demir   etkin 
2       Mehmet  Kaya    askida
3       Zeynep  Arslan  askida
4       Emre    Yıldız  etkin 
```

Blokta iki alışkanlık gömülü. Birincisi, güncellemeden önce **aynı koşulla** bir `SELECT`
çalıştırmaktır: hangi satırların etkileneceği önce görülür. İkincisi, güncellemeden sonra
etkilenen satır sayısını okumaktır. Beklenen sayı biliniyorsa — burada bir — sapma anında
fark edilir.

Güncelleme kısıtları atlamaz. `durum` sütununa listede olmayan bir değer yazan bir
güncelleme, ekleme sırasındakiyle aynı `CHECK` hatasını üretir. Şemadaki kısıtlar yazma
yollarının tamamında geçerlidir.

## Koşulun Unutulması

Aşağıdaki blok, koşulu olmayan bir güncellemenin ne yaptığını gösterir. Deyimin kendisi
bir öncekiyle aynıdır, yalnızca `WHERE` cümlesi yoktur.

```sh
sqlite3 :memory: <<'SQL'
.headers on
.mode column
CREATE TABLE uye (
  uye_id INTEGER PRIMARY KEY,
  ad     TEXT NOT NULL,
  soyad  TEXT NOT NULL,
  durum  TEXT NOT NULL DEFAULT 'etkin'
           CHECK (durum IN ('etkin', 'askida', 'kapali'))
);
INSERT INTO uye VALUES (1,'Ayşe','Demir','etkin'),(2,'Mehmet','Kaya','etkin'),
                       (3,'Zeynep','Arslan','askida'),(4,'Emre','Yıldız','etkin');

UPDATE uye SET durum = 'askida';
SELECT changes() AS etkilenen;

SELECT * FROM uye;
SQL
```

```
etkilenen
---------
4        
uye_id  ad      soyad   durum 
------  ------  ------  ------
1       Ayşe    Demir   askida
2       Mehmet  Kaya    askida
3       Zeynep  Arslan  askida
4       Emre    Yıldız  askida
```

Dört satır. Hata yok, uyarı yok, onay sorusu yok. Kütüphanenin bütün üyeleri askıya
alındı ve bunu söyleyen tek şey `changes()` çıktısındaki sayıdır.

Zararın ölçeği tablonun büyüklüğüyle orantılıdır. Dört satırlık bir örnekte sonuç bir
saniyede görülür; dört yüz bin satırlık bir üye tablosunda, eski değerlerin nerede
tutulduğu sorusuna dönüşür. Eski değerler hiçbir yerde tutulmaz — güncelleme yerinde
yapılır. Geri dönüş yolu yedekten kurtarmadır ve o da yedeğin alındığı ana kadardır.

Aynısı silme için de geçerlidir ve orada daha keskindir: koşulsuz bir `DELETE`, tablonun
bütün satırlarını kaldırır.

## Geri Alınabilir Alışkanlık

Bu riskin karşılığı dikkat değil, yordamdır. Yazma deyimi açık bir işlemin içinde
çalıştırılır; etkilenen satır sayısı okunur; sayı beklendiği gibiyse işlem
kesinleştirilir, değilse geri alınır.

```sh
sqlite3 :memory: <<'SQL'
.headers on
.mode column
CREATE TABLE uye (
  uye_id INTEGER PRIMARY KEY,
  ad     TEXT NOT NULL,
  soyad  TEXT NOT NULL,
  durum  TEXT NOT NULL DEFAULT 'etkin'
);
INSERT INTO uye VALUES (1,'Ayşe','Demir','etkin'),(2,'Mehmet','Kaya','etkin'),
                       (3,'Zeynep','Arslan','askida'),(4,'Emre','Yıldız','etkin');

BEGIN;
UPDATE uye SET durum = 'askida';
SELECT changes() AS etkilenen;
ROLLBACK;

SELECT * FROM uye;
SQL
```

```
etkilenen
---------
4        
uye_id  ad      soyad   durum 
------  ------  ------  ------
1       Ayşe    Demir   etkin 
2       Mehmet  Kaya    etkin 
3       Zeynep  Arslan  askida
4       Emre    Yıldız  etkin 
```

Aynı koşulsuz güncelleme çalıştı, aynı dört satırı etkiledi, sonra `ROLLBACK` deyimi
hepsini geri aldı. Tablo işlem öncesindeki hâlindedir: üçüncü üye askıda, diğerleri etkin.

`BEGIN` ile başlayan bir işlem, `COMMIT` görene kadar kalıcı değildir. Bu, elle yazılan
her yazma deyiminin varsayılan çerçevesi olmalıdır. Deyim doğruysa `COMMIT`, sayı
şaşırtıcıysa `ROLLBACK` yazılır — ve şaşırtıcı sayıyı görme fırsatı ancak işlem açıkken
vardır.

İşlemlerin ayrıntısı — yalıtım düzeyleri, kilitleme, kısmi geri alma — İleri SQL kursunun
konusudur. Burada gereken tek şey çerçevedir.

## Koşulu Sorgudan Almak

Güncellenecek satırlar bir sorgunun sonucuyla belirlenebilir. Bu, "iade edilmemiş ve
tarihi geçmiş ödüncü olan üyeleri askıya al" gibi kuralları tek deyimde yazmayı sağlar.

```sh
sqlite3 :memory: <<'SQL'
.headers on
.mode column
CREATE TABLE uye (uye_id INTEGER PRIMARY KEY, ad TEXT NOT NULL, soyad TEXT NOT NULL,
                  durum TEXT NOT NULL DEFAULT 'etkin');
CREATE TABLE odunc (odunc_id INTEGER PRIMARY KEY, kitap_id INTEGER NOT NULL,
                    uye_id INTEGER NOT NULL, alis_tarihi TEXT NOT NULL, iade_tarihi TEXT);
INSERT INTO uye VALUES (1,'Ayşe','Demir','etkin'),(2,'Mehmet','Kaya','etkin'),
                       (3,'Zeynep','Arslan','etkin');
INSERT INTO odunc VALUES
  (1, 1, 1, '2024-11-01', NULL),
  (2, 2, 2, '2025-06-01', NULL),
  (3, 3, 3, '2024-12-15', '2025-01-02');

BEGIN;
UPDATE uye
SET durum = 'askida'
WHERE uye_id IN (SELECT uye_id FROM odunc
                 WHERE iade_tarihi IS NULL AND alis_tarihi < '2025-01-01');
SELECT changes() AS etkilenen;
COMMIT;

SELECT * FROM uye;
SQL
```

```
etkilenen
---------
1        
uye_id  ad      soyad   durum 
------  ------  ------  ------
1       Ayşe    Demir   askida
2       Mehmet  Kaya    etkin 
3       Zeynep  Arslan  etkin 
```

Yalnızca birinci üye askıya alındı: ikincinin ödüncü açık ama tarihi yeni, üçüncününki
eski ama iade edilmiş. Alt sorgu her iki koşulu birlikte uyguladı.

Bu yazımın sınanabilir olması bir yan yarardır: alt sorgu, güncellemeden önce tek başına
`SELECT` olarak çalıştırılabilir ve hangi kimliklerin döndüğü görülür. Alt sorguların
ayrıntılı ele alınışı İleri SQL kursuna aittir; burada kullanımı koşul yazmakla sınırlıdır.

## Silme ve Bağlı Satırlar

`DELETE` deyiminin yapısı daha da kısadır: hangi tablo ve hangi satırlar.

```sh
sqlite3 :memory: <<'SQL'
.headers on
.mode column
CREATE TABLE odunc (odunc_id INTEGER PRIMARY KEY, kitap_id INTEGER NOT NULL,
                    uye_id INTEGER NOT NULL, alis_tarihi TEXT NOT NULL, iade_tarihi TEXT);
INSERT INTO odunc VALUES
  (1,1,1,'2023-01-10','2023-01-24'),
  (2,2,1,'2023-02-02','2023-02-20'),
  (3,1,2,'2025-02-11',NULL),
  (4,3,3,'2025-03-01','2025-03-15');

DELETE FROM odunc WHERE iade_tarihi IS NOT NULL AND iade_tarihi < '2024-01-01';
SELECT changes() AS silinen;

DELETE FROM odunc;
SELECT changes() AS silinen;
SELECT count(*) AS kalan FROM odunc;
SQL
```

```
silinen
-------
2      
silinen
-------
2      
kalan
-----
0    
```

İkinci deyimde koşul yoktu ve tablo boşaldı. Bu yüzden silme deyimleri, güncellemeden de
sıkı bir yordamla yazılır: önce koşulun `SELECT count(*)` ile sayılması, sonra işlem
içinde silme.

Bir satırın silinmesi ona bağlı satırları da ilgilendirir. Yabancı anahtar tanımına
eklenen davranış, motorun ne yapacağını belirler. Kısıtlayıcı davranışta silme reddedilir.

```sh
sqlite3 :memory: <<'SQL'
.headers on
.mode column
PRAGMA foreign_keys = ON;
CREATE TABLE uye (uye_id INTEGER PRIMARY KEY, ad TEXT NOT NULL, soyad TEXT NOT NULL);
CREATE TABLE odunc (
  odunc_id    INTEGER PRIMARY KEY,
  kitap_id    INTEGER NOT NULL,
  uye_id      INTEGER NOT NULL REFERENCES uye(uye_id) ON DELETE RESTRICT,
  alis_tarihi TEXT NOT NULL
);
INSERT INTO uye VALUES (1,'Ayşe','Demir'),(2,'Mehmet','Kaya');
INSERT INTO odunc VALUES (1,1,1,'2025-02-11');

DELETE FROM uye WHERE uye_id = 1;
DELETE FROM uye WHERE uye_id = 2;
SELECT changes() AS silinen;
SELECT * FROM uye;
SQL
```

```
Runtime error near line 14: FOREIGN KEY constraint failed (19)
silinen
-------
1      
uye_id  ad    soyad
------  ----  -----
1       Ayşe  Demir
```

Ödüncü olan üye silinemedi, olmayan silindi. Yayılan davranışta ise bağlı satırlar da
kaldırılır.

```sh
sqlite3 :memory: <<'SQL'
.headers on
.mode column
PRAGMA foreign_keys = ON;
CREATE TABLE uye (uye_id INTEGER PRIMARY KEY, ad TEXT NOT NULL, soyad TEXT NOT NULL);
CREATE TABLE odunc (
  odunc_id    INTEGER PRIMARY KEY,
  kitap_id    INTEGER NOT NULL,
  uye_id      INTEGER NOT NULL REFERENCES uye(uye_id) ON DELETE CASCADE,
  alis_tarihi TEXT NOT NULL
);
INSERT INTO uye VALUES (1,'Ayşe','Demir'),(2,'Mehmet','Kaya');
INSERT INTO odunc VALUES (1,1,1,'2025-01-10'),(2,2,1,'2025-02-02'),(3,1,2,'2025-02-11');

DELETE FROM uye WHERE uye_id = 1;
SELECT changes() AS silinen_uye;
SELECT * FROM odunc;
SQL
```

```
silinen_uye
-----------
1          
odunc_id  kitap_id  uye_id  alis_tarihi
--------  --------  ------  -----------
3         1         2       2025-02-11 
```

Tek bir üye silindi, onunla birlikte iki ödünç kaydı da gitti. Etkilenen satır sayısı
yine `1` yazıyor: sayaç, deyimin doğrudan hedeflediği tabloya bakar, yayılan silmeleri
saymaz. Yayılan davranışın seçilmesi, ödünç geçmişinin üyeyle birlikte yok olmasını göze
almak demektir. Kütüphane kayıtları gibi geçmişin değerli olduğu alanlarda satır silmek
yerine kaydı kapalı işaretlemek — üyeye `kapali` durumu vermek — daha uygun bir tasarımdır.

## Özet

- `UPDATE` ve `DELETE` deyimlerinde koşul cümlesi isteğe bağlıdır; yazılmadığında deyim
  tablodaki bütün satırları etkiler ve motor uyarı vermez.
- Etkilenen satır sayısı her yazma deyiminden sonra okunur; beklenen sayıdan sapma,
  yanlış koşulun tek erken göstergesidir.
- Elle yazılan yazma deyimleri işlem içinde çalıştırılır: sayı doğruysa kesinleştirilir,
  değilse geri alınır.
- Güncellenecek satırlar bir alt sorguyla belirlenebilir; alt sorgu, deyimden önce tek
  başına çalıştırılarak sınanır.
- Silmenin bağlı satırlara etkisi yabancı anahtar tanımında yazılır; yayılan silme
  geçmişi de götürdüğü için, kayıtların değerli olduğu alanlarda kapatma tercih edilir.

## Sonraki Adım

Buraya kadarki deyimler tabloların üzerinde doğrudan çalıştı. Sonraki ders araya bir
katman koyar: sorgunun kendisine ad vererek tablo gibi kullanılan görünümler. Görünüm
veriyi çoğaltmaz, sorguyu saklar — ve bu da ilginç bir soruyu doğurur: bir görünüme satır
eklenebilir mi, güncellenebilir mi. Yanıtı görünümün nasıl tanımlandığına ve motora
bağlıdır; o dersin bir bölümü bunu deneyerek gösterir.
