SQL DELETE sorgusu neden tüm satırları siliyor sorusunun temel cevabı, sorguda satırları filtreleyen WHERE koşulunun bulunmaması ya da bulunan koşulun tablodaki bütün satırlarla eşleşmesidir. Bir DELETE işlemi tabloyu tamamen kaldırmaz; eşleşen satırları siler, tablo yapısı ve sütunlar yerinde kalır.
Bu nedenle DELETE çalıştırmadan önce hedef satırları aynı koşulla SELECT kullanarak görmek, güvenli bir kontrol adımıdır.
SQL DELETE neden tüm satırları siliyor?
WHERE kullanılmadan yazılan bir DELETE sorgusu, tablodaki bütün satırları hedefler:
DELETE FROM ogrenciler;
Bu sorguda satırları sınırlayan bir koşul olmadığı için ogrenciler tablosunda bulunan tüm kayıtlar silinir. Ancak ogrenciler tablosunun kendisi, sütunları ve tablo yapısı kaldırılmaz. Tabloyu kaldıran işlemler farklıdır.
Bir WHERE koşulu eklemek de tek başına yeterli güvence oluşturmaz. Koşul, mevcut verilerin tamamıyla eşleşiyorsa sonuç yine bütün satırların silinmesi olabilir. Örneğin tabloda şu kayıtların bulunduğunu düşünelim:
| id | ad | sınıf | danışman_id |
|---|---|---|---|
| 1 | Ada | 9 | NULL |
| 2 | Deniz | 10 | 4 |
| 3 | Ece | 11 | NULL |
| 4 | Mert | 12 | 7 |
Aşağıdaki koşulda 9, 10, 11 ve 12. sınıfların tamamı kapsandığı için örnek tablodaki dört satırın hepsi hedeflenir:
DELETE FROM ogrenciler
WHERE sinif >= 9;
Buradaki sorun, WHERE yazılmış olması değil, koşulun beklenenden geniş olmasıdır. Bir sorgunun güvenli olup olmadığını anlamak için “WHERE var mı?” sorusunun yanında “Bu koşul tam olarak hangi satırları seçiyor?” sorusunu da sormak gerekir.
WHERE koşulunun hedeflediği satırlar nasıl denetlenir?

Koşulları denetlerken önce küçük parçaları ayrı ayrı inceleyebilirsin. Eşitlik için = kullanılır:
SELECT *
FROM ogrenciler
WHERE sinif = 10;
Bu sorgu örnek veride yalnızca Deniz kaydını döndürür. Aralık kontrolünde BETWEEN ya da karşılaştırma operatörleri kullanılabilir:
SELECT *
FROM ogrenciler
WHERE sinif BETWEEN 9 AND 10;
Birden fazla koşulu birlikte uygulamak için AND, alternatif koşullar için OR kullanılır:
SELECT *
FROM ogrenciler
WHERE sinif = 10
AND danisman_id IS NOT NULL;
SELECT *
FROM ogrenciler
WHERE sinif = 9
OR sinif = 12;
İlk sorgu, sınıfı 10 olan ve danışman bilgisi bulunan satırı seçer. İkinci sorgu ise sınıfı 9 veya 12 olan kayıtları getirir. AND ve OR birlikte kullanıldığında parantezler koşul grubunu açıkça gösterir:
SELECT *
FROM ogrenciler
WHERE (sinif = 9 OR sinif = 12)
AND danisman_id IS NULL;
Bu örnekte önce 9 veya 12. sınıf koşulu değerlendirilir, ardından danışman bilgisi boş olanlar seçilir. NULL değerleri için = NULL yazılmaz. Boş değeri denetlemek için IS NULL, dolu değeri denetlemek için IS NOT NULL kullanılır.
En güvenli kontrol sırası, silme sorgusundaki WHERE bölümünü önce SELECT ile çalıştırmaktır. Dönen satırları ve etkilenecek kayıt sayısını incele, koşulun parantezlerini ve NULL kontrollerini doğrula, ardından aynı koşulu DELETE sorgusuna taşı. SQL ve yazılım öğrenme sürecinde farklı konulardaki açıklamalar için yazılım üzerine bilgi verici içerikler bölümünü de inceleyebilirsin.
Öğrenciler tablosunda önce SELECT, sonra DELETE nasıl çalışır?

DELETE çalıştırmadan önce aynı WHERE koşulunu SELECT içinde denemek, hangi satırların hedefleneceğini görmeni sağlar. DELETE ifadesi, WHERE koşulunu sağlayan satırların tamamını siler; koşul hiç yazılmazsa tablodaki tüm satırlar hedeflenebilir.
Aşağıdaki örnek yalnızca çalışma amacıyla oluşturulan bir test tablosu içindir. Gerçek veritabanındaki tablo üzerinde doğrudan denemek yerine ayrı bir test tablosu veya güvenli bir deneme ortamı kullan.
CREATE TABLE ogrenciler (
id INTEGER PRIMARY KEY,
ad VARCHAR(50),
sinif VARCHAR(10)
);
INSERT INTO ogrenciler (id, ad, sinif) VALUES
(1, 'Ayşe', '10A'),
(2, 'Mert', '10A'),
(3, 'Deniz', '11A');
SELECT id, ad, sinif
FROM ogrenciler
WHERE sinif = '10A';
DELETE FROM ogrenciler
WHERE sinif = '10A';
SELECT id, ad, sinif
FROM ogrenciler;
İlk SELECT sorgusunun beklenen sonucu: sinif = '10A' koşulunu sağlayan iki satır listelenir.
| id | ad | sinif |
|---|---|---|
| 1 | Ayşe | 10A |
| 2 | Mert | 10A |
Ardından aynı koşulla çalışan DELETE yalnızca bu iki satırı siler. Son SELECT sorgusunda ise farklı sınıftaki öğrenci kalır:
| id | ad | sinif |
|---|---|---|
| 3 | Deniz | 11A |
Beklenenden fazla satır silinirse neden nasıl teşhis edilir?
Beklenenden fazla satır silindiğinde sorguyu adım adım incelemek, sorunun koşulda mı yoksa beklenen veri kapsamının tanımında mı olduğunu anlamayı kolaylaştırır.
- Çalıştırılan DELETE ifadesini kontrol et. Sorguda gerçekten
WHEREbulunup bulunmadığını incele. ÖrneğinDELETE FROM ogrenciler;ifadesinde satırları daraltan bir koşul yoktur. - Aynı koşulu SELECT ile sınayarak satırları gözden geçir. Silme işleminden önce
SELECT * FROM ogrenciler WHERE ...sorgusunu çalıştır. Listelenen satırlar beklediğin kapsamdan fazlaysa sorunDELETEişleminden önce, koşulun kendisindedir. - AND ve OR kapsamını parantezlerle netleştir. Birden fazla koşul kullanıyorsan, hangi koşulların birlikte değerlendirilmesi gerektiğini açıkça yaz. Örneğin
WHERE (sinif = '10A' OR sinif = '11A') AND durum = 'pasif'ifadesi, iki sınıftan yalnızca pasif durumdaki satırları hedefler. - NULL karşılaştırmalarını kontrol et. Bir sütundaki eksik değerleri ararken
kolon = NULLyerinekolon IS NULLkullanılır. Eksik değerleri de kapsaması gereken bir koşulda bu ayrım, eşleşen satır sayısını değiştirebilir. - Etkilenen satır sayısını beklentinle karşılaştır. Beklentinde iki satır varsa, aynı koşulla yapılan
SELECT COUNT(*)sonucunun da iki olması beklenir.DELETEsonrasında bildirilen etkilenen satır sayısını bu değerle karşılaştır. Sayının nasıl ve nerede gösterildiği, kullanılan veritabanı motoruna ve istemciye göre değişebilir.
Güvenli DELETE sırası ve transaction nasıl uygulanır?
DELETE sorgusunu güvenli çalıştırmanın temel yolu, önce aynı koşulla hangi kayıtların seçildiğini görmek, ardından silme işlemini denetlemektir. Böylece yanlış WHERE koşulunu kalıcı bir silme işlemine dönüştürmeden önce fark edebilirsin.
Güvenli DELETE sırası
- Aynı
WHEREkoşuluyla önceSELECTçalıştır. - Dönen satırların kimlik ve diğer ayırt edici alanlarını denetle.
- Mümkünse sınırlı bir test tablosunda veya uygun bir transaction içinde dene.
- İstemcinin bildirdiği etkilenen satır sayısını, beklediğin sonuçla karşılaştır.
- Sonuç uygunsa
COMMITile işlemi kalıcılaştır. Uygun değilseROLLBACKkullan.
Transaction, birden fazla SQL adımını tek bir işlem birimi gibi yönetir. COMMIT, açık transaction içindeki değişiklikleri kalıcılaştırır. ROLLBACK ise henüz kalıcılaştırılmamış değişiklikleri geri alma amacı taşır. Bu nedenle ROLLBACK'in daha önce COMMIT edilmiş bir silmeyi kesin olarak geri getireceği varsayılmamalıdır.
Örneğin, ogrenciler tablosunda durum = 'mezun' olan iki kayıt bulunduğunu varsayalım. START TRANSACTION destekleyen bir ortamda önce sonucu kontrol edip ardından silme işlemini deneyebilirsin:
START TRANSACTION;
SELECT id, ad
FROM ogrenciler
WHERE durum = 'mezun';
DELETE FROM ogrenciler
WHERE durum = 'mezun';
ROLLBACK;
SELECT iki satır döndürdüyse DELETE sonrasında etkilenen satır sayısının da beklenen sonucu yansıtması gerekir. Kontrol tamamlandıktan sonra işlem doğruysa son satır COMMIT ile değiştirilir. Transaction başlatma ve otomatik kalıcılaştırma davranışı veritabanı motoruna ve istemci ayarlarına göre değişebileceğinden, kullanılan ortamın belgeleri ayrıca kontrol edilmelidir.
Programlama bilgini ve algoritmik düşünme becerilerini değerlendirmek için bilgi testleri merkezini kullanabilirsin.
Kısacası, güvenli bir DELETE işlemi önce seçimi görünür kılar, sonra sonucu denetler ve en son kalıcılaştırır.