Tetikleyiciler (TRIGGER) Bir tetikleyici bir tabloya bağlı olarak bir takım işlemler yapan özel bir saklı yordamdır. Biz bu derste sadece Ardı Sıra Tetikleyici (After Trigger) ve Yerine Tetikleyici (Instead Of Triggers) adı verilen tetikleyicileri tanıtacağız. Tetikleyiciler ne zaman kullanılırlar Tetikleyicileri kullanmanın bir çok nedeni vardır. Bir tabloda bir değişiklik yapıldığında ayni anda bir çok değişik işlemin de yapılması gerekli olabilir. Belki de bu tabloda yapılan değişikliklerin veritabanı sorumlusuna bir e-mail atması istenebilir. Bu işlemler için tetikleyiciler kullanmak çoğu kez çok zarif çözümler üretmenizi sağlayabilir. Ardı Sıra Tetikleyiciler (After Triggers) Bir tabloya UPDATE, INSERT veya DELETE işlemi yapıldıktan sonra bir takım işlemlerin yapılması için kullanılan tetikleyicilere Ardı Sıra Tetikleyici denir. Bu tür tetikleyiciler pek çok değişik iş yapabilirler. Bir başka tabloya veri girişi yapmak veya tabloyu güncellemek, tablolar arasında uyumu sağlamak için bu tür tetikleyiciler çok uygundur. Örnek 1. Bu örnekte öncelikler üç tablo oluşturalım. Müşteriler, Kitaplar ve Satışlar CREATE TABLE Müşteriler ( MüşteriNo int IDENTITY (1, 1) NOT NULL, AD nvarchar (20), SOYAD nvarchar(20) ) CREATE TABLE Ürünler ( ÜrünNo int IDENTITY (1, 1) NOT NULL, ÜrünAD nvarchar (255), Stok int ) CREATE TABLE Satışlar ( FişNo int IDENTITY (1, 1) NOT NULL, MüşteriNo int, ÜrünNo int, Adet int, Tarih smalldatetime ) VALUES ('Yusuf','Ünlü') VALUES ('Orhan','Sönmez') VALUES ('Naime','Ekici')
VALUES ('Modern Cebir, Herstein, Academic Press',5) VALUES ('Analiz, Rudin, Van Nostrand',4) VALUES ('Geometri, Coxeter, North Holland',2) VALUES ('Şu Çılgın Türkler, Özakman',450) CREATE TRIGGER SatışGir_StokGüncelle ON Satışlar FOR INSERT DECLARE @Say int SELECT @SAY = COUNT(i.ÜrünNo) FROM Ürünler u INNER JOIN inserted i ON u.ürünno = i.ürünno WHERE (i.adet > u.stok) IF @Say >0 BEGIN ROLLBACK TRANSACTION RAISERROR ('Girilen ürünlerden biri stokdan fazla',16,1) END ELSE UPDATE Ürünler SET Stok = u.stok - i.adet FROM Ürünler u INNER JOIN inserted i ON u.ürünno = i.ürünno Burada inserted olarak adlandırılan tablo yeni bir kayıt girilmekte olan Satışlar tablosunda yeni kayıtın girildiği satırdan oluşan tablonun tetikleyicide kullanılan mantıksal adıdır. Tetikleyicinin ne yaptığı son derece açıktır. Eğer yeterli stok varsa satış yapıldıktan sonra satış adedini stoktan düşmektedir. Bunun için bir örnek verelim. SELECT * FROM Ürünler INSERT INTO Satışlar( MüşteriNo,ÜrünNo,Adet,Tarih) VALUES ( 1,2,1, '2.2.2005') SELECT * FROM Ürünler Stok kontrolü yapmayan bir tetikleyici daha basit yazılabilir 2. Bir DELETE tetikleyici yazalım
CREATE TRIGGER SatışSil_StokGüncelle ON Satışlar FOR DELETE UPDATE Ürünler SET Stok = p.stok + i.adet FROM Ürünler p JOIN deleted i ON p.ürünno = i.ürünno Bu tetikleyiciyi deneyelim SELECT * FROM Satışlar DELETE FROM WHERE FişNo = 2 Satışlar Burada deleted olarak adlandırılan tablo kayıt silinmekte olan Satışlar tablosunda silinen kayıttan oluşan tablonun tetikleyicide kullanılan mantıksal adıdır. Tetikleyici iptal edilen satış adedini stoka eklemektedir. 3. Bir UPDATE tetikleyici yazalım. Burada UPDATE işleminin sadece bir tek satır üzerinde yapıldığı varsayılmaktadır. CREATE TRIGGER SatışGüncelle_StokGüncelle ON Satışlar FOR UPDATE DECLARE @STOK int, @ÜrünNo int, @Eski_Adet int, @Yeni_Adet int SELECT @ÜrünNo = ÜrünNo, @Yeni_Adet = Adet FROM inserted SELECT @Eski_Adet = Adet FROM deleted SELECT @STOK = Stok FROM Ürünler IF @Stok + @Eski_Adet - @Yeni_Adet < 0 ROLLBACK TRANSACTION ELSE UPDATE Ürünler SET Stok = Stok + @Eski_Adet - @Yeni_Adet Burada deleted olarak adlandırılan tablo kayıt değiştirilmeden önce Satışlar tablosunda değiştirilmekte olan kayıttan oluşan tablonun tetikleyicide kullanılan mantıksal adıdır. inserted ise ayni satırın kayıt değiştirildikten sonra elde edilen satırdan oluşan tablonun tetikleyicide kullanılan mantıksal adıdır. Bunun nedeni aslında UPDATE bir DELETE ve INSERT işleminin ard arda uygulanması gibi düşünülmelidir. Yerine Tetikleyiciler( INSTEAD OF TRIGGER) Bir INSERT, UPDATE veya DELETE işlemi bir tabloya uygulandığında bu tablo üzerinde, sırasıyla bir Instead Of INSERT, Instead Of UPDATE veya Instead Of DELETE tetikleyici varsa bu işlem tablo üzerinde gerçekleşmez. Onun yerine tetikleyici içinde yazılı kodlar yapılır. Örnek:
CREATE TABLE DENEME ( N int IDENTITY (1, 1) NOT NULL, Ad varchar(32), SilmeGirişimi datetime) CREATE TRIGGER deltrig_deneme ON Deneme INSTEAD OF DELETE UPDATE Deneme SET SilmeGirişimi = GETDATE() WHERE N IN (SELECT N FROM DELETED) INSERT Deneme(Ad) values('yusuf') INSERT Deneme(Ad) values('orhan') INSERT Deneme(Ad) values('naime') DELETE Deneme WHERE N=1 DELETE Deneme WHERE N=2 Bir INSTEAD OF INSERT örneği verelim. CREATE TABLE DenemeTablo (BirincilAnahtar int IDENTITY(1,1), Renk nvarchar(10) NOT NULL, Kumaş nvarchar(10) NOT NULL, FormülleHesaplananKolon (Renk + Kumaş) ) CREATE VIEW DenemeTabloİçinSanalTablo SELECT BirincilAnahtar, Renk, Kumaş, FormülleHesaplananKolon FROM DenemeTablo CREATE TRIGGER YerineTetikleyici on DenemeTabloİçinSanalTablo INSTEAD OF INSERT BEGIN INSERT INTO DenemeTablo SELECT Renk, Kumaş FROM inserted END INSERT INTO DenemeTablo (Renk, Kumaş) VALUES ('Kırmızı', 'Keten') SELECT BirincilAnahtar, Renk, Kumaş, FormülleHesaplananKolon FROM DenemeTablo Şimdi bu tabloya hatalı bir giriş yapmaya çalışalım. Bu girişin hatalı olmasının nedeni, IDENTITY kolona bir değer girime girişimi ve formülle hesaplanan bir kolona giriş yapılmaya çalışılmasıdır.
INSERT INTO DenemeTablo VALUES (2, 'Pembe', 'İpek', 'Pembeİpek') Yukarıdaki hatalı giriş yerine şimdi yerine tetikleyicinin devreye girmesini sağlayan bir giriş yapalım. Bu tetikleyici DenemeTabloİçinSanalTablo için yazıldığından INSERT işlemini bu VIEW için yapmaya çalışalım. INSERT INTO DenemeTabloİçinSanalTablo (BirincilAnahtar, Renk, Kumaş, FormülleHesaplananKolon) VALUES (999, 'Mavi', 'Pamuk', 'XXXXXX') Şimdi bir hata olmadan giriş yapıldığını görelim. SELECT BirincilAnahtar, Renk, Kumaş, FormülleHesaplananKolon FROM DenemeTabloİçinSanalTablo