SQL Server Trigger’ları: Veri Tabanında “Arka Planda Çalışan Gizli Yardımcılar”

Veritabanı üzerinde çalışmaya başladığınızda, bazen bazı işlerin sizin haberiniz bile olmadan otomatik yürüdüğünü fark edersiniz. Bir tabloya veri eklenir, başka bir tablo kendiliğinden güncellenir. Bir kaydı silersiniz, ilgili kayıtların başka bir tabloda yok olduğunu görürsünüz. Sanki görünmez bir el perde arkasından sistemi düzenliyordur.
İşte bu görünmez elin adı trigger’dır.
Trigger, kelime anlamına uygun şekilde bir tetikleyicidir. Bir tabloda belirli bir olay gerçekleştiğinde devreye girer ve sizin belirlediğiniz işi yapar. Bu iş çoğu zaman log tutmak, başka bir tabloyu güncellemek, audit kaydı eklemek ya da sistemin bütünlüğünü korumaktır.
İşin güzel tarafı şu: Trigger bir kez yazılır, gerisini o halleder. Sizin sürekli kontroller yazmanıza gerek kalmaz.
Trigger Neden Vardır?
Gerçek hayattan küçük bir örnek düşünelim. Bir mağazanın stok yönetimi sistemi olsun. Müşteri bir ürün satın aldığında kasiyerin ayrıca “Stoktan 1 adet düş” butonuna basması gerekse, hata yapılması kaçınılmazdır. İş yoğunluğunda unutulur, yanlış düşülür, raporlar şaşar.
Bunun yerine sistem şöyle çalışsa daha mantıklı olmaz mı?
“Satış tablosuna bir kayıt eklendiğinde, stok tablosundaki ilgili ürün miktarını otomatik bir şekilde azalt.”
İşte trigger tam da burada devreye girer. Satış kaydı eklendiği anda, stok tablosundaki ilgili ürünü günceller. Kasiyerin ya da geliştiricinin ekstra bir şey yapmasına gerek kalmaz.
Yani trigger, sistemin kendi kendini yönetmesini sağlar.
Trigger Türleri Nelerdir?
SQL Server’da üç temel tetikleyici türü vardır:
1. AFTER Trigger (Olaydan Sonra Çalışanlar)
Bu tip trigger, INSERT, UPDATE veya DELETE işlemi başarıyla tamamlandıktan sonra devreye girer. En çok kullanılan trigger türüdür.
Örneğin:
Bir kullanıcı tablosunda yapılan değişiklikleri audit tablosuna yazmak için AFTER UPDATE trigger yazılır. Güncelleme başarılıysa trigger çalışır, değilse çalışmaz.
2. INSTEAD OF Trigger (Olayın Yerine Geçenler)
Bazen veritabanının belirli bir işlem yapmasını istemezsiniz. Örneğin bir view üzerinden silme işlemi gelir ama gerçekte alttaki tabloda silinmesini istemezsiniz. Bunun yerine “sildi gibi davran ama aslında başka bir tabloya taşı” diyebilirsiniz.
INSTEAD OF trigger tam olarak bunu yapar. Asıl işlem yerine sizin yazdığınız kodu çalıştırır.
3. DDL Trigger (Tablo Değişikliklerini İzleyenler)
Bu grup genellikle sistem yöneticilerinin favori aracıdır. Çünkü veritabanındaki yapısal değişiklikleri takip eder. Birisi yanlışlıkla bir tabloyu silmeye kalksa ya da bir kolon eklese, bu trigger sizi bilgilendirebilir.
Örneğin:
Bir kişi production ortamındaki bir tabloda ALTER işlemi yaparsa, anında bir log tablosuna kayıt yazdırabilir veya mail gönderebilirsiniz.
Trigger Nasıl Çalışır? “Inserted” ve “Deleted” Mantığı
Trigger’ın en kritik noktalarından biri inserted ve deleted adlı sanal tablolardır.
Bunlar fiziksel tablolar değildir, sadece trigger çalışırken var olurlar.
Basitçe şöyle düşünebilirsiniz:
- INSERT işleminde, eklenen satırlar inserted tablosunda bulunur.
- DELETE işleminde, silinen satırlar deleted tablosunda bulunur.
- UPDATE işleminde ise deleted eski değerleri, inserted yeni değerleri tutar.
Bu sayede trigger içinde şunu yapabilirsiniz:
“Eski ürün fiyatı ile yeni fiyatı karşılaştır, aradaki değişikliği fiyat log tablosuna yaz.”
Bu yaklaşım birçok kurumsal projede fiyat geçmişi, kullanıcı değişiklikleri, stok hareketleri gibi amaçlarla kullanılır.
Gerçek Bir Örnek Üzerinden Bakalım
Diyelim ki bir spor salonu için üyelik yönetimi yazıyorsunuz. Üye bir paket satın aldığında sistemde üç şey yapılması gerekiyor:
- Üyelik tablosuna yeni kayıt açılacak
- Stok tablosundan ilgili paket düşülecek
- Muhasebe tablosuna gelir kaydı yazılacak
Her seferinde bunları uygulama tarafında yazabilirsiniz. Ama ekip büyüdükçe herkesin farklı yöntemlerle bu işlemleri yaptığını fark edersiniz. Kimi güncelleme yapmayı unutur, kimi tabloyu kilitler, kimi eksik veri bırakır.
Bunun yerine şöyle bir trigger yazabilirsiniz:
CREATE TRIGGER tr_AfterMembershipInsert
ON Memberships
AFTER INSERT
AS
BEGIN
-- 1. Stok düş
UPDATE PackageStock
SET Quantity = Quantity - 1
WHERE PackageId IN (SELECT PackageId FROM inserted);
-- 2. Muhasebe kaydı
INSERT INTO Accounting (Amount, Description, CreatedDate)
SELECT Price, 'Üyelik Satışı', GETDATE()
FROM inserted;
END
Sonuç olarak uygulamada sadece “Memberships tablosuna yeni kayıt ekle” dersiniz. Gerisini trigger halleder.
Bu hem geliştiriciyi yormaz hem de sistemin tutarlılığını korur.
Trigger Yazmanın Avantajları
- İş mantığı veritabanı seviyesinde korunduğu için hata riski düşer.
- Aynı işlemi farklı uygulamalar çalıştırsa bile standart davranış sağlanır.
- Audit ve log mekanizmaları için idealdir.
- Uzun vadede sistemin bütünlüğünü sağlar.
Peki dezavantajları var mı?
Elbette. Trigger da yanlış kullanılırsa projeyi zorlaştırabilir.
- Arka planda çalıştığı için bazen ne olduğunu anlamak zorlaşır.
- Çok karmaşık trigger’lar performansı etkileyebilir.
- Döngüsel tetiklenmeler dikkat edilmezse zincirleme işlemlere yol açabilir.
- “Neden bu veri böyle oldu?” sorusuna cevap ararken trigger akla gelmeyebilir.
Bu yüzden trigger yazarken iki şeye özellikle dikkat etmek gerekir:
- Kod mümkün olduğunca basit olmalı
- Gereksiz iş yükü oluşturmamalı
Trigger, doğru yerde kullanıldığında inanılmaz güçlüdür ama her sorunun çözümü de trigger değildir.
Yüklü DDL İşlemleri veya Bulk Load Öncesi Trigger’ları Devre Dışı Bırakmak
Trigger’lar normal koşullarda hayat kurtarır ama iş “yüksek hacimli veri yükleme” aşamasına geldiğinde bazen işleri zorlaştırabilir. Özellikle milyonlarca satırın insert edildiği bir senaryoda, her satır için tetiklenen bir trigger sistemin performansını dramatik biçimde düşürür. Bu durumla çoğu kişi veri ambarı projelerinde ya da eski sistemlerin yeni platformlara taşınmasında karşılaşır.
Böyle durumlarda yapılan pratik bir yöntem vardır: Bulk load başlamadan önce triggerları devre dışı bırakmak, işlem bittiğinde yeniden aktif hale getirmek. Bu, SQL Server’ın tasarımında zaten düşünülmüş bir kullanım şeklidir.
Mantık basittir. Trigger çalışmazsa veritabanı sadece saf insert işlemi yapar. Böylece gereksiz hesaplamalar, log yazımları veya ek kontroller devreden çıkar ve işlem çok daha hızlı tamamlanır. Tabii burada kritik olan: Bu işlemi bilinçli bir şekilde yapmak. Çünkü disable edilen bir trigger aslında veri bütünlüğünü koruma görevini geçici olarak bırakmış olur.
Kullanım örneği şöyle görünür:
DISABLE TRIGGER tr_AfterMembershipInsert ON Memberships;
-- Burada ağır veri yükleme işlemleri yapılır
ENABLE TRIGGER tr_AfterMembershipInsert ON Memberships;
Gerçek bir örnek verirsek; bir e-ticaret şirketinde geçmiş yıllara ait sipariş verileri yeni sisteme aktarılırken yüz binlerce insert işlemi yapılmıştı. Sipariş kaydının ardından otomatik çalışan birkaç trigger vardı ve her biri stok, fatura ve log tablolarını güncelliyordu. Normal operasyon için gerekliydi, ancak bu taşımada hiçbir işlevsel anlamı yoktu. Bu nedenle triggerlar geçici olarak kapatıldı. Yükleme bittiğinde yeniden aktif hale getirildi ve sistem günlük rutinine geri döndü.
Tabii burada dikkat edilmesi gereken bir nokta var: Eğer trigger veri bütünlüğünü garantiliyorsa, bulk yük sonrası o bütünlüğün bozulup bozulmadığını kontrol etmek size kalır. Özellikle hesaplamalar, ilişkili tablolar veya log mekanizmaları devre dışı kaldığı için bazı ek doğrulamaların yapılması faydalıdır. Kimi kurumlarda bu kontrol için özel bir “sonradan tamamlama” script’i bile bulunur.
Sonuç olarak, triggerları geçici olarak kapatma konusu bir performans hilesi değil, doğru kullanıldığında operasyonel bir gerekliliktir. Önemli olan neyi, neden devre dışı bıraktığınızı bilmek ve işlem bittiğinde sistemi eski düzenine geri döndürmektir.
Son Söz
SQL Server trigger’ları, veritabanı dünyasının perde arkasındaki küçük kahramanlarıdır. Doğru kullanıldığında projenin sağlamlığını artırır, veri bütünlüğünü korur ve geliştiricinin işini kolaylaştırır. Yanlış kullanıldığında ise takip edilmesi zor bir hal alır.
Benim yaklaşımım her zaman aynıdır: Trigger, uygulamanın değil, veritabanının sorumluluğunda olması gereken işler için kullanılmalıdır. Özellikle loglama, güvenlik, otomatik tutarlılık sağlama gibi konularda bir kez doğru kurgulanan bir trigger uzun yıllar boyunca sessizce ve sorunsuzca çalışır.
Yazan : Nedim Akıl | https://www.linkedin.com/in/ndmakl/


