Trigger’lar, tablo üzerinde tanımlanabilen ve bu tablo üzerinde bir işlem gerçekleştiğinde tetiklenen programlama ögeleridir. Çalışma yapısı, C#’daki event mantığı ile aynıdır.
DML ve DDL trigger’lar olarak ikiye ayırmak mümkündür.
DML (Data Manipulation Language) => Datalar üzerinde sorgulama ve değişiklik yapmak için kullandığımız SQL deyimleridir. (SELECT,INSERT, UPDATE ve DELETE)
DDL (Data Definition Language) => CREATE, ALTER ve DROP komutlarına verilen isimdir.
Bu yazımızda DML Trigger’lar üzerinde inceleme yapacağız. Insert, Update ve Delete işlemleri için arka planda oluşan ‘insterted’ ve ‘deleted’ tablolarını kullanacağız. Bu tablolar hakkında daha detaylı bilgiye şuradan erişebilirsiniz.
DML Trigger’ları da kendi içinde AFTER(ya da FOR) ve INSTEAD OF olmak üzere ikiye ayrılırlar. ( AFTER ve FOR birebir aynı anlamdadır. FOR anahatar sözcüğü, eski SQL sürümlerindeki alışkanlığı devam ettirmek amacı ile kullanılabilir kılınmıştır.)
AFTER => Bu trigger’lar tetiklendiğinde işlem gerçekleşmiş demektir. Yani yazdığımız trigger ‘after delete’ şeklindeyse, o tablo üzerinde data silindikten sonra bu trigger devreye girer.
INSTEAD OF => Bu trigger’lar tetiklendiğinde işlem gerçekleşmemiştir. Yani yazdığımız trigger ‘instead of delete’ şeklindeyse, o tablo üzerindeki kayıt silme işlemi yerine, bu trigger devreye girecektir.
Tanımlarken biraz karmaşık gelse de örnekler üzerinde daha iyi anlaşılacağını düşünüyorum. İlk olarak AFTER Trigger’ı ile ilgili inceleme yapalım.
Örneğimize başlamadan önce, Urun ve Siparis adında iki adet tablo oluşturalım.
CREATE TABLE Urun
(
UrunID INT PRIMARY KEY IDENTITY(1,1),
UrunAd NVARCHAR(50),
StokMiktar INT
)
CREATE TABLE Siparis
(
SiparisID INT PRIMARY KEY IDENTITY(1,1),
UrunID INT,
SiparisMiktar INT
)
Şimdi de bu iki tablo arasında ilişki olduğunu, Siparis kolonundaki UrunID’nin, Urun tablosunda referans olacağını belirtelim.
ALTER TABLE Siparis
ADD CONSTRAINT FK_Siparis_UrunID FOREIGN KEY(UrunID)
REFERENCES Urun(UrunID)
Bu constraint(kısıtlama) sayesinde, Siparis tablosundaki UrunID kolonuna, Urun tablosunda kayıtlı olmayan bir ID girişi yapılamaz.
Şimdi de Urun tablomuza birkaç adet ürün insert edelim.
INSERT INTO Urun VALUES('Kitap',500)
INSERT INTO Urun VALUES('Defter',740)
INSERT INTO Urun VALUES('Silgi',220)
Urun tablosundaki görüntümüz aşağıdaki gibidir.
Görüldüğü gibi, Urun tablomuza 3 adet ürün girişi yaptık ve bu ürünlerin stok miktarlarını tutuyoruz. Şimdi de Siparis tablosuna insert yapalım. Ancak siparişi verirken, girmiş olduğumuz sipariş miktarı kadar, Urun tablosunda o ürün için tutulan StokMiktarının da azalmasını istiyoruz. Bunun için bir trigger yazalım. Bahsettiğimiz olay, Siparis tablosuna data girişi yapıldığında tetiklenmelidir. Dolayısı ile AFTER INSERT için bir trigger yazmalıyız.
CREATE TRIGGER TRG_StokDusur
ON Siparis
AFTER INSERT
AS
DECLARE @urunId INT
DECLARE @siparisMiktar INT
SELECT @urunId=UrunID,@siparisMiktar=SiparisMiktar FROM inserted
UPDATE Urun SET StokMiktar=StokMiktar-@siparisMiktar
WHERE UrunID=@urunId
Artık Siparis tablosunda yapılan her insert’den sonra, bu trigger devreye girecektir. Şimdi de Siparis tablosuna insert yapalım.
INSERT INTO Siparis VALUES(1,100) --ID'si 1 olan Kitap adlı ürün için 100 adet sipariş verdik.
Yukarıdaki kodu çalıştırdığımızda aşağıdaki mesajlı alırız.
Görüldüğü gibi, yapmış olduğumuz insert 2 farklı tabloyu etkilemiş durumda. Yazdığımız trigger sayesinde Urun tablosundaki StokMiktarı da update edilmiş oldu.
Urun tablosundaki kayıtları tekrar görüntüleyelim.
İstediğimiz sonucu elde etmiş durumdayız. İik durumda Kitap adlı üründen 500 adet mevcuttu. Ancak 100 adet sipariş verdiğimizde, Urun tablosundaki stoktan da 100 adet düşüldüğünü ve Stok miktarının 400 olduğunu görüyoruz.
Şimdi de Kitap ve Arşiv adında iki tablo oluşturalım.
CREATE TABLE Kitap
(
KitapID INT PRIMARY KEY IDENTITY(1,1),
KitapAd NVARCHAR(50),
Yazar NVARCHAR(50)
)
CREATE TABLE Arsiv
(
KitapID INT,
KitapAd NVARCHAR(50),
Yazar NVARCHAR(50),
SilindigiTarih DATETIME
)
Kitap tablomuza birkaç adet insert yapalım.
INSERT Kitap VALUES('Melekler ve Şeytanlar','Dan Brown')
INSERT Kitap VALUES('Gece Gelen Ölüm','Agatha Christie')
Amacımız, Kitap tablosundan bir kayıt silindiğinde, silinen datanın o anki tarih bilgisi ile birlikte Arsiv tablosuna kaydedilmesini sağlayan bir trigger yazmak.
CREATE TRIGGER TRG_ArsiveTasi
ON Kitap
AFTER DELETE
AS
INSERT INTO Arsiv
SELECT *,GETDATE() FROM deleted
Şimdi de Kitap tablosundaki ‘Melekler ve Şeytanlar’ adlı kaydı silelim.
DELETE Kitap WHERE KitapID=1
Yukarıdaki örnekte olduğu gibi, yaptığımız işlemin 2 tablo üzerinde etkili olduğuna dair bir mesaj alacağız.
Arşiv tablomuzu görüntülediğimizde, sildiğimiz datanın buraya kaydedildiğini görebiliriz.
Şimdi de INSTEAD OF Trigger’ları ile ilgili bir örnek yapalım. Araba adında bir tablo oluşturalım.
CREATE TABLE Araba
(
ArabaID INT PRIMARY KEY IDENTITY(1,1),
Marka NVARCHAR(20),
Model NVARCHAR(20),
Aktif BIT
)
ALTER TABLE Araba
ADD CONSTRAINT DF_Araba_Aktif DEFAULT 1 FOR Aktif
Not: Aktif adlı kolonun tipi BIT olduğundan, 0 veya 1 değerlerini tutabilir. Yazdığımız constraint(kısıtlama) ile bu kolona değer girilmesse, Default olarak 1 değerini verilmesini sağladık.
Oluşturduğumuz tabloya birkaç data girişi yapalım.
INSERT INTO Araba(Marka,Model) VALUES('Renault','Megane')
INSERT INTO Araba(Marka,Model) VALUES('Ford','Focus')
INSERT INTO Araba(Marka,Model) VALUES('Audi','A3')
Araba adlı tablomuzun görüntüsü aşağıdaki gibidir.
Insert ettiğimiz datalar için Aktif kolonuna değer girmememize rağmen, istediğimiz gibi default olarak 1 gelmiş durumda. Şimdi de bu tablo üzerinde yapılacak bir delete işlemi için bir trigger yazalım. Yazdığımız trigger, kaydı silmeyerek, Aktif kolonuna 0 değerini atasın. Yani silme işlemi yerine update işlemi yapacağız. Dolayısı ile delete işleminin yerine başka bir iş yaptırmış olacağız.
CREATE TRIGGER TRG_PasifYap
ON Araba
INSTEAD OF DELETE
AS
UPDATE A SET Aktif=0 FROM Araba A
JOIN deleted D ON A.ArabaID=D.ArabaID
Araba tablosundan bir kayıt silelim ve tabloyu görüntüleyelim.
DELETE Araba WHERE ArabaID=2
Görüldüğü gibi yapmış olduğumuz silme işlemi gerçekleşmedi. Onun yerine, yazmış olduğumuz trigger devreye girerek, silinmek istenen datanın Aktif kolonundaki değerini 0’a update etti.
Faydalı olması dileği ile…
25 yorum:
yazını için çook teşekür ederim web tasarımcı olarak çook işme yarayacak bir olay :D
Yorumunuz için ben teşekkür ederim, işinize yaramasına sevindim. İyi çalışmalar..
Bir matematik mühendisi olarak seni tebrik ederim Onur yazdıkların çok başarılı :)
Gamze
Çok teşekkür ederim Gamze, faydalı olması dileği ile...
süper olmuş, merak eder dururdum nedir bu trigger diye sayende çok iyi anladım. öğretmen olmalısın sen.. tebrikler. ferit
Çok faydalı bir makale olmuş tebrik ederim. Elinize sağlık. Başarılarınızın devamını dilerim.
eline salık emeğine sağlık
triggerla oluşturduğum bir tabloya aynı trigger içinde nasıl trigger ekleyebilirim?
RSS listeme eklendin .Tebrikler
Teşekkürler
çok yararlı bilgi...eline sağlık
çok teşekkürler.. ellerinize sağlık..
faydalı paylaşım için teşekkür ederim.
Adamsın..
Teşekkürler çık faydalı bir yazı olmuş.
gayet anlaşır bir yazı olmuş, elinize sağlık
Süper bir anlatım olmuş süper.
Çok İyi Ama Eksik diye düşünüyorum neyse beğendim!
Teşekkür ederim Onur.
Çok teşekkürler. Harika bir anlatım olmuş.
nice job. thanks dude.
hocam bu from dan sonraki INSERTED ve DELETED dememizin mantığı ne
Anlatım cok iyi gercekten teşekkürler harika
Üstad eline sağlık,update için de bir örnek verir misin ?
iki aynı tablo ve veriler,birinde bir veri değişince diğerinde de aynı verinin değişmesi için nasıl bir yol izlemeliyiz ?
Merhaba,
Öncelikle teşekkür ederim. İlgili örneğe aşağıdaki linkten ulaşabilirsiniz.
http://onursalkaya.blogspot.com.tr/2011/12/sql-trigger-kavram-ii.html
Yorum Gönder