Alper ÇELİK

Bilgisayar Mühendisi

Trigger_2

Bir önceki seride After(For) trigger konusuna değinmiştik. Bu bölümde Instead Of Trigger konusuna giriş yapıyoruz. Trigger'lar her zaman olay olduktan sonra devreye giren yapılar değildirler. Instead of trigger'ları tablo değişikliğinden etkilenmeden hemen önce devreye giren yapılardır. 2 yapıyı birbirinden ayıran yegane özellik; AFTER trigger'lar sadece tablolar üzerinde tanımlanabilirken, INSTEAD OF trigger'lar hem tablolar hemde view'ler üzerinde tanımlanabilirler. Bunun dışında AFTER trigger'lar işlem yapıldıktan sonra tetiklenirken INSTEAD OF trigger'lar işlem yapılmadan önce tetiklenirler. (hatta INSTEAD OF trigger'lar, constraint'ler bile devreye girmeden önce tetiklenirler ama sözde tablolara ilgili işlem yansıtıldıktan sonra devreye girerler.)  
 Önemli Not: Bir tablo üstünde instead of trigger'ı tanımlanacaksa, bu tablo üstünde daha önceden CASCADE UPDATE ve CASCADE DELETE işlemleri için tanımlı constraint olmaması gerekir.
 
 
 INSTEAD OF ile AFTER trigger arasındaki önemli farklar:   
 
* Instead of trigger'lar view veya tablolar için kullanılabilir ancak After trigger'lar sadece tablolar için kullanılabilir,
* Instead of trigger'lar her view'de işlem başına sadece bir adet bulunabilir fazlası için yeni bir view tanımlayıp o view üzerinde tekrar trigger tanımlamanız gerekir ancak After trigger için her tabloda birden fazla trigger tanımlanabilir.  
 
-------------------------------------------------------------------------    
 
Resim-1'de belirtildiği gibi 2 adet tablom var, şimdi bunları view haline dönüştürelim:
 
CREATE VIEW vw_EmployeeDetails  
AS
SELECT te.ID, te.Name, te.Gender, td.DeptName  
FROM tblDepartment td INNER JOIN tblEmployees te ON te.DepartmentID=td.DeptID
 
 
INSERT INTO vw_EmployeeDetails VALUES(6, 'Jack', 'Male', 'HR')    
 
Şayet ben view'e şu şekilde bir insert işlemi yapmak istersem bana aşağıdaki gibi hata verecektir.  
 
"Msg 4405, Level 16, State 1, Line 1  
View or function 'vw_EmployeeDetails' is not updatable because the modification affects multiple base tables."   
 
View'e eklediğim satır 2 ana tabloyu etkilediği için böyle bir kayıt gerçekleştiremeyeceğini söylüyor. Yani hangi kayıt hangi tabloya gidecek SQL Server eldeki bilgileriyle buna karar veremiyor da diyebiliriz.
Bu noktada işimizi çözecek olan yapı INSTEAD OF TRIGGER'dır. vw_EmployeeDetails view'i için yazacağımız trigger aşağıdaki gibi olacaktır.  
 
 
CREATE TRIGGER trg_vw_EmployeeDetails_INSTEADOFINSERT
ON vw_EmployeeDetails
INSTEAD OF INSERT
AS
BEGIN
 DECLARE @DeptID INT
 SELECT @DeptID=DeptID FROM tblDepartment t JOIN inserted i ON i.DeptName= t.DeptName
 
 IF(@DeptID IS NULL)
 BEGIN  
 RAISERROR('Invalid Department Name. Statement Terminated',16,1)
 RETURN
 END
 INSERT INTO tblEmployees( Name, Gender, DepartmentID)
 SELECT  Name, Gender, @DeptID FROM inserted
END  
 
Şimdi bu trigger'ı, olmayan bir departman üzerinden test edelim. Bakalım kod gövdesindeki gibi hata fırlatılacak mı..
 
INSERT INTO vw_EmployeeDetails VALUES(6, 'Jack', 'Male', 'ABCD' )  
 
Bu sorgu ile view'e bir satır kayıt eklemek istediğimizde bize hata sonucu döndürecektir. Çünkü tblDepartment tablosunda olmayan bir kayıt 'ABCD' eklemek istiyoruz.
 
Sorgumuzu şu şekilde değiştirdiğimizde ilgili kaydımız sağlıklı bir şekilde çalışacaktır.
INSERT INTO vw_EmployeeDetails VALUES(6, 'Jack', 'Male', 'IT' )  
 
 Not:  Bir trigger'ın INSTEAD OF trigger olup olmadığını anlamak için, OBJECTPROPERTY fonksiyonundan faydalanırız. Yukarıda oluşturduğumuz trigger üzerinden test edecek olursak yazım şekli şöyle olur:  
 
 
SELECT OBJECTPROPERTY(OBJECT_ID('trg_vw_EmployeeDetails_INSTEADOFINSERT'), 'execisInsteadOfTrigger')  
 
Şayet geriye 1 dönerse INSTEAD OF trigger, 0 dönerse AFTER trigger demektir.  

Trigger Serisinin İlk Bölümüne Buradan Ulaşabilirsin

Trigger'lar özelleşmiş bir tür stored prosedürlerdir(SP).