Kurs
SQL'de veri silme potansiyel olarak riskli bir işlemdir. Kötü yazılmış tek bir komut, tablolar arasındaki ilişkileri bozabilir veya tüm bir veri kümesini silebilir.
Bu eğitimde, DELETE ifadesinin nasıl çalıştığını, onu doğru şekilde nasıl kullanacağınızı ve az önce bahsettiğim gibi, tüm bir veri kümesini silmek gibi yaygın hatalardan nasıl kaçınacağınızı göstereceğim.
SQL'e yeniyseniz, Introduction to SQL kursumuzla başlayın veya biraz deneyiminiz varsa Intermediate SQL kursunu deneyin.
DELETE SQL'de Ne İşe Yarar?
Sözdizimine bakmadan önce, DELETE ifadesinin gerçekte ne yaptığını anlamak önemlidir. SQL'de verileri kaldırmanın farklı biçimleri aşağıdadır.
Kavramsal olarak SQL DELETE ve satırları kaldırma
DELETE ifadesi, bir tablonun yapısını korurken bir veya daha fazla satırı kaldırır. Dolayısıyla sütun adları, veri türleri, indeksler ve kısıtlar gibi tablo şeması olduğu gibi kalır. Silme işleminden sonra tablo varlığını sürdürür ve yeni verileri kabul etmeye hazırdır.
Bunu, sayfaları koparmak değil, bir defterden girileri silmek gibi düşünün. Şema aynı kalır; yalnızca seçili kayıtlar kaldırılır.
SQL DELETE vs. DROP vs. TRUNCATE
Her ne kadar DELETE, DROP ve TRUNCATE bir biçimde veri kaldırsalar da, çok farklı amaçlara hizmet ederler. Aşağıdaki tablo her ifadenin kullanımını özetler:
|
Özellikler |
DELETE |
TRUNCATE |
DROP |
|
Komut Türü |
DDL (Data Definition Language) |
||
|
Kapsam |
Belirli satırları kaldırır ( |
Bir tablodaki tüm satırları kaldırır |
Tüm tabloyu ve verilerini kaldırır. |
|
Hız |
Daha yavaş (satır satır kaldırır) |
Daha hızlı (sayfaları serbest bırakır) |
Anında |
|
Geri Döndürülebilirlik |
Geri alınabilir |
Geri döndürülemez |
Geri döndürülemez. |
|
Tablo Yapısı |
Korunur |
Korunur (ve kimlikleri sıfırlar) |
Tamamen silinir |
Temel SQL DELETE Sözdizimi
Artık DELETE ifadesinin nasıl çalıştığını anladığınıza göre, sözdizimine ve nasıl uygulanacağına bakalım.
WHERE ile belirli satırları silme
WHERE koşulu, bir DELETE işleminin kapsamını tanımlar. Veritabanına tam olarak hangi satırların kaldırılması gerektiğini söylediği için WHERE koşulu her zaman gereklidir.
-- Basic DELETE syntax
DELETE FROM table_name
WHERE condition;
Bir tablodaki tüm satırları silme
DELETE ifadesinde WHERE koşulunu atlamanız durumunda, SQL tablodaki her bir satırı hedeflemek istediğinizi varsayar. Bunu yanlışlıkla yaparsanız, veritabanı motoru tek tek her kaydı gözden geçirip siler. Silinen her satır için işlem günlüğüne bir kayıt düşülür. Milyonlarca satırınız varsa bu çok yavaş olabilir ve günlük dosyalarınızın şişmesine neden olabilir.
SQL DELETE Güvenli Uygulamalar
Bir DELETE işlemi kalıcı olabileceğinden, güvenli silme uygulamalarını hayata geçirmek yavaşlamanıza, niyeti doğrulamanıza ve bir şeyler ters gittiğinde/nasıl kurtaracağınıza dair plan yapmanıza yardımcı olur.
Silmeden önce satırları önizleme
DELETE ifadesini çalıştırmadan önce, kaldırmayı planladığınız satırları, DELETE'te kullanmayı planladığınızla aynı WHERE koşuluna sahip bir SELECT ifadesiyle mutlaka önizleyin. SELECT ifadesi çok fazla satır veya yanlış satırlar döndürürse, herhangi bir zarar oluşmadan önce koşulu düzeltebilirsiniz.
Örneğin, aşağıdaki sorgu 2023-01-01 tarihinden önce iptal edilmiş siparişleri kontrol eder ve ardından bu kayıtları silmek için aynı filtreleri kullanır.
-- Step 1: Preview the targets
SELECT * FROM Orders
WHERE Status = 'Cancelled' AND OrderDate < '2023-01-01';
-- Step 2: Once you've verified the list, convert to DELETE
DELETE FROM Orders
WHERE Status = 'Cancelled' AND OrderDate < '2023-01-01';
İşlemler ve geri alma kullanımı
DELETE işlemini bir işlemin (transaction) içine alırsanız, bir komutu çalıştırmanıza, kaç satırın etkilendiğini görmenize ve ardından değişikliği kalıcı hale getirip getirmemeye veya tamamen geri almaya karar vermenize olanak tanır. Ardından ROLLBACK kullanarak verileri önceki durumuna geri yükleyebilirsiniz.
Aşağıdaki sorgu, uygun satırları geçici olarak siler ve ardından geri yükler; böylece veri kaybetmeden etkiyi doğrulamanıza imkân tanır.
BEGIN TRANSACTION;
DELETE FROM Users
WHERE LastLogin < '2020-01-01';
-- Inspect the affected row count
ROLLBACK;
Ardından aşağıdaki sorguyu kullanarak 1 Ocak 2020'den önce son kez oturum açmış kullanıcıları kalıcı olarak silebilirsiniz.
BEGIN TRANSACTION;
DELETE FROM Users
WHERE LastLogin < '2020-01-01';
-- Confirm deletion of the required rows
COMMIT;
Ancak, ROLLBACK'in yalnızca işlemi henüz commit etmediyseniz mümkün olduğunu unutmamalısınız.
Join ve Alt Sorgularla SQL DELETE
Gerçek dünyadaki veritabanlarında, veriler nadiren izole halde bulunur. Çoğu durumda, başka tablolarda tutulan değerlere, süresi dolmuş hesaplara, yetim kayıtlara veya artık geçerli olmayan ilişkili varlıklara göre satırları silmeniz gerekebilir.
Başka bir tabloya göre satır silme
Alt sorgular kullanmak, başka bir tabloya göre satır silmek için en taşınabilir ve en yaygın desteklenen yaklaşımdır. Neredeyse tüm SQL sürümlerinde çalışırlar. Örneğin, aşağıdaki sorgu, Accounts tablosunda hesabı devre dışı bırakılmış olan Users tablosundaki etkin olmayan kullanıcıları siler.
-- Delete users whose accounts have been deactivated
DELETE FROM Users
WHERE AccountId IN (
SELECT AccountId
FROM Accounts
WHERE Status = 'DEACTIVATED'
);
Veritabanında satır silmek için Join'ler de kullanılabilir, ancak sözdizimi veritabanına göre değişir; bunu bir sonraki bölümde göreceğiz.
Veritabanına özgü DELETE sözdizimi
SQL'de DELETE ifadesinin fikri aynı olsa da, JOIN kullanarak bir tablodan diğerine göre satır silerken farklı veritabanlarının farklı sözdizimleri vardır.
SQL Server hedef tabloyu DELETE ifadesinden sonra, ardından FROM içinde join'ler. Aşağıdaki örnekte, DELETE'ten sonraki kısaltma (u) hangi tablonun silindiğini belirtir.
-- SQL Server: Delete users linked to deactivated accounts
DELETE u
FROM Users u
JOIN Accounts a
ON u.AccountId = a.AccountId
WHERE a.Status = 'DEACTIVATED';
PostgreSQL'de USING bir JOIN gibi davranır. Yalnızca hedef tablodaki (Users) satırlar silinir.
-- PostgreSQL: Delete users linked to deactivated accounts
DELETE FROM Users
USING Accounts
WHERE Users.AccountId = Accounts.AccountId
AND Accounts.Status = 'DEACTIVATED';
MySQL çoklu tablo silmelerine izin verir ancak tablo adının açıkça belirtilmesini gerektirir. Silinecek tabloyu FROM ifadesinden önce yerleştirmelisiniz.
-- MySQL: Delete users linked to deactivated accounts
DELETE u
FROM Users u
JOIN Accounts a
ON u.AccountId = a.AccountId
WHERE a.Status = 'DEACTIVATED';
Şunu öneririm: Joining Data in SQL kursumuzu alarak SQL'de farklı join türlerini ve veritabanındaki ilişkili farklı tablolarla nasıl çalışılacağını öğrenin.
SQL DELETE ve Bağlamsal Bütünlük
Artık biliyoruz ki, ilişkisel bir veritabanında tablolar nadiren tek başına bulunur. Genellikle yabancı anahtarlar kullanılarak birbirine bağlanırlar. Bu bağlantılar nedeniyle, bir tabloda bir satırı silmek istenmeyen sonuçlara yol açabilir.
Yabancı anahtarlar ve kısıtlama hataları
Bir tablo bir yabancı anahtar tarafından başvurulduğunda, veritabanı, bir üst satırı silmeye çalıştığınızda ne olacağına dair kuralları uygular. Varsayılan olarak, çoğu veritabanı, alt tabloda ilişkili satırlar hâlâ varsa silmeyi engeller.
Örneğin, Orders tablosunun Customers tablosuna başvurduğu bir durumda, hâlâ siparişi bulunan bir müşteriyi silmek, bir kısıtlama hatasıyla başarısız olur. Bu, veritabanını geçerli bir üst öğesi olmayan yetim kayıtlar içermekten korur.
Kaskat silmeler
İlişkili verileri otomatik olarak silmek istiyorsanız, veritabanına ilişkili verileri nasıl ele alacağını söyleyen bir kademeli (cascading) kuralı açıkça tanımlamanız gerekir. ON DELETE CASCADE, bir üst satır kaldırıldığında ilişkili alt satırların otomatik olarak silinmesini söyler.
Örneğin, aşağıdaki sorgu, Customers tablosundan bir müşteri silindiğinde, o müşteriye referans veren Orders tablosundaki tüm satırların otomatik olarak silinmesini veritabanına bildirir.
-- Parent table
CREATE TABLE Customers (
CustomerId INT PRIMARY KEY,
Name VARCHAR(100)
);
-- Child table with a cascading foreign key
CREATE TABLE Orders (
OrderId INT PRIMARY KEY,
CustomerId INT,
OrderDate DATE,
CONSTRAINT fk_orders_customers
FOREIGN KEY (CustomerId)
REFERENCES Customers(CustomerId)
ON DELETE CASCADE
);
Bu yaklaşımın avantajı, birden çok manuel DELETE ifadesi gerektirmeden veritabanını temiz tutmasıdır. Ancak, tek bir silmenin birden çok tablo arasında zincirleme bir tepkiyi tetikleyerek beklenenden çok daha fazla veriyi kaldırabileceği için ifadeyi dikkatli kullanmalısınız. Örneğin, Departments tablosunda bir satırı siler ve yanlışlıkla Employees tablosunda 500 satırı silebilirsiniz.
Veri Silerken Performansla İlgili Hususlar
DELETE ifadesini kullandıkça, birkaç satır silmenin anlık olduğunu, ancak milyonlarca satır varsa yavaşladığını fark edeceksiniz. Kayıtları güvenle silmek için şu en iyi uygulamaları değerlendirin:
Büyük tablolar için DELETE vs. TRUNCATE
Daha önce gördüğümüz gibi, DELETE ve TRUNCATE kayıtları şu şekillerde kaldırır:
-
DELETE: Her satırı tek tek inceler, ölçütleri karşılayıp karşılamadığını kontrol eder, kaldırır ve değişikliği işlem günlüğüne kaydeder. Çok büyük veri kümeleri için kaynak tüketimi fazladır ve yavaştır.WHEREkoşuluyla filtrelemeye izin verir ve geri almayı destekler. -
TRUNCATE: Tüm satırları aynı anda asgari günlüklemeyle kaldırır. Kayda değer ölçüde daha hızlıdır ancak filtrelenemez, genellikle geri alınamaz ve yabancı anahtar kısıtları tarafından engellenir.
Toplu silmeler ve uzun süreli işlemler
Tek bir ifadeyle milyonlarca satır silerseniz, bu tüm uygulamanızı önemli ölçüde yavaşlatabilir ve doğru şekilde ele alınmazsa veritabanınızın çökmesine bile neden olabilir. Bu riski azaltmak için, büyük veri kümelerini her zaman partiler (batch) halinde silin.
Toplu silmeler, her işlemde birkaç bin gibi sınırlı sayıda satırı kaldırır. Bu, veritabanının duyarlı kalmasını sağlar ve ilerlemenin kolay izlenmesine olanak tanır. Bir şeyler ters giderse, devasa bir işlemi geri almak zorunda kalmadan süreci durdurabilirsiniz.
SQL DELETE Sık Yapılan Hatalar
Tablolarınızdaki satırları kaldırmak için DELETE ifadesini kullanırken dikkat etmeniz gereken yaygın hatalar şunlardır:
WHERE koşulunu unutmak
DELETE kullanırken en yaygın hata WHERE koşulunu unutmaktır. Bu olmadan ifade, tablodaki her satırı kaldırır. Hangi satırları sileceğinizi belirtmek için her zaman WHERE koşulunu kullandığınızdan emin olun. Önleyici bir önlem olarak, satırları silmeden önce görmenizi sağlayan daha önce bahsettiğimiz DELETE'ten önce SELECT alışkanlığını kullanın.
DELETE'in geri döndürülebilir olduğunu varsaymak
Bir diğer yaygın yanlış kanı, silinen verilerin her zaman kurtarılabileceğidir. Varsayılan olarak, DELETE ifadesi commit edildikten sonra, yedekler, replikalar veya denetim günlükleri yoksa verileri diskten fiziksel olarak kaldırılmış olarak işaretlediğini unutmayın.
Bir DELETE komutunu yalnızca şu durumlarda “geri alabilirsiniz”:
- Bir işlem içinde yürütülmüşse.
- İşlem commit edilmemişse.
- Veritabanı ve depolama motoru geri almayı destekliyorsa.
Canlı (Prod) Ortamlarda SQL DELETE
Canlı sistemlerde, DELETE işlemi sözdiziminden ziyade kontrol, görünürlük ve hesap verebilirlikle ilgilidir. Bu tür ortamlarda amaç yalnızca veriyi kaldırmak değil, bunu güvenle ve bilinçli şekilde yapmaktır.
Erişim kontrolü ve izinler
Profesyonel bir ortamda, veri silme yetkisi En Az Ayrıcalık İlkesine uymalıdır. Her kullanıcı veya uygulama servis hesabı DELETE izinlerine sahip olmamalıdır.
Çoğu "Salt Okunur" kullanıcı veya raporlama aracına bu hak açıkça reddedilmelidir. Çoğu şirket genellikle bir “Akran İncelemesi” ister; burada, üretimde çalıştırılmadan önce manuel silme betiğinin WHERE koşulunun ikinci bir kişi tarafından doğrulanması gerekir.
İşinizin bir parçası olarak düzenli olarak veritabanı tasarlıyor veya bakımı yapıyorsanız, SQL Server for Database Administrators yetkinlik yolunu denemenizi öneririm; düzenli olarak veritabanları tasarlıyor veya bakımını yapıyorsanız.
Denetim ve yumuşak silmeler (soft delete)
Birçok canlı sistem, riskleri nedeniyle sert silmelerden kaçınır. Bunun yerine, bir satırın silinmiş olarak işaretlendiği yumuşak silmeleri kullanırlar. Örneğin, bir kaydı fiziksel olarak kaldırmak yerine bir deleted_at zaman damgası veya is_deleted bayrağı kullanabilirsiniz.
Yumuşak silmeler, kurtarmayı kolaylaştırır, denetimi destekler ve hata ayıklama ile uyumluluk amaçları için geçmiş verileri korur.
Sonuç
En önemli çıkarım şudur: Her zaman net bir WHERE koşulu tanımlayın, etkilenen satırları SELECT ile önizleyin ve mümkün olduğunda işlemleri kullanın. Canlı sistemlerde her silme işlemi kasıtlı ve denetlenebilir olmalıdır. DELETE'i, bir şema değişikliği veya dağıtım kadar dikkatle ele alın; böylece maliyetli bir hatadan ziyade faydalı bir araç olarak kalır.
Şunu öneririm: Database Design kursumuzu alarak veritabanlarını oluşturmayı ve yönetmeyi, ayrıca ihtiyaçlarınıza uygun VTYS'yi seçmeyi öğrenin. Ayrıca, veri mühendisliği ve veri ambarı temellerini öğrenmek için Associate Data Engineer in SQL kariyer yolumuzu denemenizi de tavsiye ederim.
SQL DELETE SSS
DELETE, TRUNCATE veya DROP'tan nasıl farklıdır?
DELETE seçili satırları kaldırır, TRUNCATE tüm satırları hızla kaldırır ve DROP tablonun kendisini siler.
DELETE'te WHERE koşulu neden önemlidir?
WHERE koşulu olmadan, DELETE tüm satırları kaldırır ve tam veri kaybı riski doğurur.
Bazı DELETE işlemleri neden başarısız olur?
Yabancı anahtar kısıtları, kaskat kurallar olmadan bağımlı alt satırlar varsa silmeyi engeller.
Silinecekleri güvenle nasıl önizleyebilirim?
Aynı WHERE koşuluyla bir SELECT ifadesi kullanarak silmeden önce etkilenecek satırları inceleyin.
Büyük veri kümelerini güvenle nasıl silebilirim?
Uzun süren işlemler ve performans sorunlarını önlemek için satırları partiler hâlinde silen toplu silmeleri kullanın.
