Gereksinimler ve Ön Hazırlık
SQL triggerları kullanabilmek için modern bir ilişkisel veritabanı yönetim sistemine (RDBMS) ihtiyacınız vardır. Bu rehberde genel SQL standartlarını ve yaygın olarak kullanılan PostgreSQL ile MySQL sözdizimlerini temel alacağız. Çalışma ortamınızda şu bileşenlerin hazır olduğundan emin olun:
- PostgreSQL 16+ veya MySQL 8.4+ sürümü kurulu bir veritabanı sunucusu.
- Veritabanı üzerinde
TRIGGERoluşturma yetkisine sahip bir kullanıcı hesabı. - Veritabanı işlemlerini yönetmek için bir SQL istemcisi (DBeaver, pgAdmin veya MySQL Workbench).
Başlamadan önce, üzerinde işlem yapacağımız örnek bir tablo yapısı kuralım. Senaryomuz, bir e-ticaret sistemindeki "siparişler" tablosuna yeni bir kayıt eklendiğinde "stok" tablosunu güncelleyen bir sistem üzerine kurulu olacaktır.
-- Örnek tablo yapısı
CREATE TABLE stoklar (
urun_id INT PRIMARY KEY,
stok_miktari INT NOT NULL
);
CREATE TABLE siparisler (
siparis_id SERIAL PRIMARY KEY,
urun_id INT,
adet INT
);
Trigger Yapısı ve Temel Sözdizimi
Bir trigger oluştururken dikkat etmeniz gereken en önemli husus, tetikleyicinin işlemin "öncesinde" (BEFORE) mi yoksa "sonrasında" (AFTER) mı çalışacağıdır. BEFORE tetikleyicileri genellikle veri doğrulaması için kullanılırken, AFTER tetikleyicileri veri tutarlılığını sağlamak veya log tutmak için tercih edilir.
Aşağıdaki örnekte, bir sipariş girildiğinde stok miktarını otomatik olarak azaltan bir trigger yapısını inceleyelim:
-- PostgreSQL için örnek trigger fonksiyonu
CREATE OR REPLACE FUNCTION stok_dusur()
RETURNS TRIGGER AS $$
BEGIN
UPDATE stoklar
SET stok_miktari = stok_miktari - NEW.adet
WHERE urun_id = NEW.urun_id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
Bu kod bloğu, tetikleyici çalıştığında devreye girecek olan mantıksal fonksiyonu tanımlar. NEW anahtar kelimesi, tabloya yeni eklenen satırı temsil eder.
Adım Adım Trigger Oluşturma Uygulaması
Trigger fonksiyonunu tanımladıktan sonra, bu fonksiyonu spesifik bir tabloya ve olaya bağlamanız gerekir. İşte bir sipariş eklendiğinde tetiklenecek olan asıl tetikleyici tanımı:
-- Trigger'ı siparişler tablosuna bağlama
CREATE TRIGGER siparis_eklendikten_sonra
AFTER INSERT ON siparisler
FOR EACH ROW
EXECUTE FUNCTION stok_dusur();
Bu komut, siparisler tablosuna her yeni satır eklendiğinde, stok_dusur fonksiyonunu çalıştırır. FOR EACH ROW ifadesi, etkilenen her bir satır için işlemin tekrarlanmasını sağlar.
Trigger Yönetimi ve Karşılaştırma Tablosu
Trigger kullanırken hangi yöntemin projenize uygun olduğunu belirlemek için aşağıdaki karşılaştırma tablosunu inceleyebilirsiniz:
| Özellik | BEFORE Trigger | AFTER Trigger |
|---|---|---|
| Kullanım Amacı | Veri doğrulama, formatlama | Loglama, ilişkili tablo güncelleme |
| Performans | Daha hızlı (işlem öncesi) | İşlem tamamlandıktan sonra |
| Güvenlik | Veri manipülasyonuna açık | Daha kontrollü |
Yaygın Hatalar ve Debug İpuçları
Trigger yazarken en sık karşılaşılan hata "sonsuz döngü" (infinite loop) durumudur. Örneğin, bir tabloda güncelleme yapan bir trigger, aynı tabloyu güncelleyen başka bir trigger'ı tetiklerse sistem kilitlenebilir. Bunu engellemek için her zaman koşullu ifadeler (IF blokları) kullanın.
-- Koşullu trigger örneği (Sadece stok yeterliyse işlem yap)
CREATE OR REPLACE FUNCTION stok_kontrol_ve_dusur()
RETURNS TRIGGER AS $$
BEGIN
IF (SELECT stok_miktari FROM stoklar WHERE urun_id = NEW.urun_id) >= NEW.adet THEN
UPDATE stoklar SET stok_miktari = stok_miktari - NEW.adet WHERE urun_id = NEW.urun_id;
ELSE
RAISE EXCEPTION 'Yetersiz stok!';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
Bu örnekte RAISE EXCEPTION kullanarak, stok yetersiz olduğunda işlemin tamamen geri alınmasını (rollback) sağlıyoruz.
Güvenlik Uyarısı: Triggerlar veritabanı seviyesinde çalıştığı için karmaşık mantıklar performans sorunlarına yol açabilir. Üretim ortamında (production) trigger kullanmadan önce mutlaka yük testi yapın ve SQL Injection riskine karşı veritabanı kullanıcı yetkilerini kısıtlayın.
Sıkça Sorulan Sorular
Triggerları veritabanında nasıl listelerim?
PostgreSQL'de SELECT * FROM information_schema.triggers; sorgusu ile tüm tetikleyicileri listeleyebilirsiniz.
Bir trigger'ı geçici olarak nasıl devre dışı bırakırım?
MySQL'de ALTER TABLE tablo_adi DISABLE TRIGGER trigger_adi; komutu ile tetikleyiciyi durdurabilirsiniz.
Triggerlar performans kaybı yaratır mı?
Evet, özellikle çok sayıda satırı etkileyen toplu işlemlerde (bulk insert) triggerlar ciddi performans kaybına neden olabilir. Bu durumlarda triggerları geçici olarak kapatmak en iyi pratiktir.
Aynı tabloya birden fazla trigger eklenebilir mi?
Evet, aynı olay (örneğin AFTER INSERT) için birden fazla tetikleyici tanımlayabilirsiniz; ancak bunların çalışma sırasını yönetmek karmaşık olabilir.
Trigger içerisinde başka bir veritabanına bağlanabilir miyim?
Doğrudan SQL trigger içerisinde başka bir veritabanına bağlanmak önerilmez. Bu tür işlemler için uygulama katmanında (Backend) servisler kullanmanız daha güvenlidir.
İleri Seviye Trigger Stratejileri: Audit Log Uygulaması
Veritabanı güvenliği ve denetlenebilirlik (auditing) için trigger kullanımı, endüstriyel standartlarda kritik bir rol oynar. Bir tablo üzerinde yapılan her değişikliği, kimin, ne zaman ve hangi değerle yaptığını takip etmek için ayrı bir "Log" tablosu oluşturmak en profesyonel yaklaşımdır.
Audit Log Tablosu Tasarımı
Öncelikle, değişiklikleri kaydedeceğimiz yapıyı kuralım. Bu tablo, ana tablodaki her satırın tarihçesini tutacaktır.
CREATE TABLE Personel_Log (
LogID INT PRIMARY KEY IDENTITY(1,1),
PersonelID INT,
EskiMaas DECIMAL(18,2),
YeniMaas DECIMAL(18,2),
DegistirenKullanici VARCHAR(100),
DegisimTarihi DATETIME DEFAULT GETDATE()
);
Dinamik Veri Takibi İçin Trigger Yazımı
Aşağıdaki trigger, Personel tablosunda bir güncelleme yapıldığında otomatik olarak devreye girer ve maaş değişikliğini log tablosuna yansıtır.
CREATE TRIGGER trg_PersonelMaasDegisim
ON Personel
AFTER UPDATE
AS
BEGIN
IF UPDATE(Maas)
BEGIN
INSERT INTO Personel_Log (PersonelID, EskiMaas, YeniMaas, DegistirenKullanici)
SELECT
i.PersonelID,
d.Maas,
i.Maas,
SYSTEM_USER
FROM inserted i
INNER JOIN deleted d ON i.PersonelID = d.PersonelID
WHERE i.Maas d.Maas;
END
END;
Trigger Performansını Optimize Etme Teknikleri
Triggerlar, veritabanı işlemlerinin bir parçası olarak çalıştığı için, yazılan kodun verimliliği doğrudan uygulamanın hızını etkiler. Performans kaybını minimize etmek için şu kurallara dikkat edilmelidir:
- Minimal İşlem: Trigger içerisinde ağır hesaplamalar, karmaşık JOIN işlemleri veya dış servis çağrılarından kaçının.
- Set-Based İşlemler: Trigger içerisinde tek bir satırı işlemek yerine,
insertedvedeletedtablolarını kullanarak toplu (batch) işlemleri destekleyin. - Koşullu Tetikleme: Trigger'ın sadece belirli sütunlar değiştiğinde çalışmasını sağlamak için
IF UPDATE(sütun_adı)kontrolünü mutlaka kullanın. - İşlem Süresi: Trigger'ın süresi, ana işlemin (INSERT/UPDATE/DELETE) süresine eklenir. Bu yüzden trigger içindeki sorguların indekslenmiş alanlar üzerinde çalıştığından emin olun.
Uzman İpucu: Eğer çok yoğun bir yazma (write-heavy) ortamında çalışıyorsanız, veritabanı triggerları yerine "Asenkron Kuyruk" (Message Queue) sistemlerini tercih etmeyi değerlendirin. Bu, veritabanı üzerindeki yükü hafifleterek uygulamanın daha ölçeklenebilir olmasını sağlar.
Test Süreçleri ve Doğrulama
Triggerlarınızı canlıya almadan önce mutlaka bir test ortamında simüle etmelisiniz. Bir trigger'ın beklenen sonucu verip vermediğini anlamak için şu basit test senaryosunu uygulayın:
- Test verisi ekleyin.
- Trigger'ın tetikleneceği işlemi (UPDATE) gerçekleştirin.
- Log tablosunu
SELECT * FROM Personel_Logile sorgulayarak verilerin doğru kaydedilip kaydedilmediğini kontrol edin. - Hata senaryoları için (örneğin boş değer girişi) trigger'ın nasıl tepki verdiğini gözlemleyin.
Sonuç
SQL ile veritabanı trigger oluşturma süreci, veritabanı mimarinizi güçlendiren ve veri tutarlılığını otomatize eden en güçlü araçlardan biridir. Bu rehberde öğrendiğiniz BEFORE ve AFTER tetikleyici mantığını, kendi projelerinizde loglama veya stok yönetimi gibi alanlarda güvenle kullanabilirsiniz. Bir sonraki adım olarak, veritabanı performansını izlemek için EXPLAIN ANALYZE komutlarını kullanarak yazdığınız triggerların sorgu sürelerine olan etkisini incelemenizi öneririm.
Not: Bu içerik, veritabanı yönetimi konusunda teknik bir rehber niteliğindedir. Uygulama öncesi mutlaka veritabanı yedeği alınız.


Yorumlar (0)
Yorum Yaz