Ana içeriğe geç
Kesit SQL
Orta · T-SQL (SQL Server)

T-SQL DML kalıpları: UPDATE FROM, DELETE JOIN, TOP ile parça parça silme, OUTPUT

Günlük T-SQL'in en sık yazımları: başka tabloya göre güncelle, sil; büyük silmeyi böl; neyin değiştiğini yakala.

Uygulamada aç, 10 alıştırmayı çözÜcretsiz, hesap gerekmez, kurulum yok.

Bu sayfa dersin okuma sürümüdür. Metin bir kutuyu çalıştırmanı ya da adıma geçmeni söylüyorsa dersi uygulamada aç.

Başka tabloya göre güncellemek

T-SQL'e özgü yazım: hedef FROM içinde tekrar yer alır, UPDATE sonrasında takma ad yazılır. Bu yazım ISO standardı değildir; aynı işi PostgreSQL UPDATE t ... FROM s, MySQL UPDATE t JOIN s ... SET ile yapar.

UPDATE p SET p.price = u.new_price
FROM products p
JOIN price_updates u ON u.product_id = p.product_id
WHERE u.new_price > p.price;
SELECT @@ROWCOUNT AS guncellenen;
BelirsizlikBir hedef satırı birden çok kaynak satırıyla eşleşirse hangisinin yazılacağı belirsizdir; hata da vermez. Önce kaynağı tekilleştir. Yukarıdaki sorguda bir ürünün birden çok fiyat kaydı varsa sonuç garanti değildir. Bu yüzden MERGE dersinde önce son kayıt seçiliyordu.

Başka tabloya göre silmek

Hedef DELETE ile FROM arasına takma adla yazılır.

DELETE i
FROM order_items i
JOIN orders o ON o.order_id = i.order_id
WHERE o.status = 'cancelled';
SELECT @@ROWCOUNT AS silinen;

Parça parça silmek

Milyonlarca satırı tek işlemde silmek günlüğü şişirir, kilitleri uzun tutar. DELETE TOP (n) döngüde çalıştırılır. TOP burada ORDER BY almaz, hangi satırların gideceği belirsizdir; bu silmede sorun değildir, çünkü hepsi gidecektir.

DECLARE @n INT = 1, @tur INT = 0;
WHILE @n > 0
BEGIN
  DELETE TOP (500) FROM bank_txns WHERE txn_time < '2024-02-01';
  SET @n = @@ROWCOUNT;
  SET @tur = @tur + 1;
END;
SELECT @tur AS tur, COUNT(*) AS kalan FROM bank_txns WHERE txn_time < '2024-02-01';

OUTPUT: neyin değiştiğini yakala

inserted yeni, deleted eski değerdir. Trigger yazmadan denetim kaydı almanın kısa yolu.

UPDATE departments SET city = N'Ankara'
OUTPUT deleted.dept_id, deleted.city AS eski, inserted.city AS yeni
WHERE dept_id = 2;

MERGE OUTPUT ve $action

MERGE'te $action satıra ne yapıldığını yazar: INSERT, UPDATE ya da DELETE. Sıra garanti değildir, sıralama gerekiyorsa sonucu tabloya alıp sırala. OUTPUT ... INTO hedefi tablo ya da tablo değişkenidir.

DECLARE @d TABLE (islem NVARCHAR(10), dept_id INT, eski NVARCHAR(50), yeni NVARCHAR(50));
MERGE departments AS t
USING (SELECT 2 AS dept_id, N'Pazarlama' AS name, N'Ankara' AS city UNION ALL SELECT 50, N'Veri', N'İzmir') AS s
   ON t.dept_id = s.dept_id
WHEN MATCHED THEN UPDATE SET city = s.city
WHEN NOT MATCHED THEN INSERT (dept_id, name, city) VALUES (s.dept_id, s.name, s.city)
OUTPUT $action, COALESCE(inserted.dept_id, deleted.dept_id), deleted.city, inserted.city INTO @d;
SELECT * FROM @d ORDER BY dept_id;
Bu motordaBu yazımlar tarayıcıdaki taklit motorda SQLite'a çevrilerek çalışır; söz dizimi ve sonuç öğretilir, günlük ve kilit etkisi görülmez.
Alıştırmalara geç (10)