Trigger Türkçe anlamı olarak Tetikleyici demektir. Trigger, Stored Procedureler gibi Sql Server içinde bileşen olarak bulunmaktadır. Triggerların kullanım amacı, tablo üzerinde bir işlem gerçekleştiğinde (insert, update, delete) başka bir işlem daha yapılmak istendiği zaman kullanılır.
Şu şekilde basit olarak örneklendirelim.
Öğrenci tablonuz olduğunu düşünelim. Öğrenci tablonuzda bir öğrenciyi sildiğinizde bu öğrenci bilgilerini daha farklı bir tabloda(silinen öğrencilerin tutulduğu) tutmak istiyorsunuz. Öğrenci tablosundaki bir kayıt silindiğinde(delete) başka bir tabloya bu kaydı trigger ile aktarmak mümkün.
Yada daha kapsamlı başka bir örnek Bir kütüphane tablosu üzeride, bir öğrenci sadece bir kitap alabilir durumda olsun. Öğrenci kitabı getirmediği sürece ikinci bir kitap almasına izin verilmesin. Bu işlemi görsel program aracılığı ile yapabileceğiniz gibi trigger ile öğrenci kitap teslim etmediyse ikinci bir kitabı almasına izin verilmesini engelleyebilirsiniz. Yazının sonunda çok daha fazla senaryo ile örneklendirme yapacağım.
Trigger’lar DML (Delete, Insert ve Update işlemleri) işlemleri üzerinde çalışırlar. Select ile bir bağlantısı yoktur. DML işlemi gerçekleştiğinde deleted, inserted yada her iki sanal tablolaya kayıtlar eklenir. Trigger tetiklenerek, trigger içindeki sorgular gerçekleştirilir. Sonra da kayıtlar gerçek tabloya(rollback ile sorguyu iptal edebiliriz) eklenerek sorgu işlemi bitirilir.
Adım adım trigger oluşturma kavramına bir bakalım.
Trigger Oluşturma
1 2 3 4 5 6 7 8 9 |
CREATE TRIGGER trigger_adi ON tablo_adi {FOR|AFTER|INSTEAD OF} {INSERT|UPDATE|DELETE} AS Begin --Sql ifadeler End |
tablo_adi: hangi tabloda çalışacağını belirtiyoruz
After yada Instead of: after yapılırsa işlem yapıldıktan sonra, instead of yapıldığında yapmak istediğimiz işlemin yerine çalıştırılacağını belirtiyoruz
Insert,Update, Delete: Tabloda hangi sql işlemi sırasında çalıştırılacağını belirtiyoruz.
Begin…..End: Trigger çalıştırıldıktan sonra yürütülecek olan sql cümlelerini bu aralıkta yazıyoruz.
Trigger Güncelleme
1 2 3 4 5 6 7 8 9 |
ALTER TRIGGER trigger_adi ON tablo_adi AFTER veya INSTEAD OF (INSERT , UPDATE , DELETE) AS Begin --Sql ifadeler End |
Inserted / Deleted Kavramları
Trigger’ın çalışmasına göre, hangi tablo üzerinde etkinse tablo üzerine eklenilen veya güncellenilen kayıtları “inserted” üzerinde, silinen kayıtları ise “deleted” üzerinde kaydediyor. Bunlar sanal tablolardır (virtual table).
Insert: Bir insert işlemi gerçekleştirdiğimizde, eklediğimiz kayıt ilk olarak inserted tablosuna eklenir.
Delete:Bir delete işlemi gerçekleştirdiğimizde sildiğimiz kayıt ilk olarak deleted tablosuna eklenir.
Update:Update işleminde ise eski kayıt önce deleted tablosuna, güncellenen(yeni) kayıt ise inserted tablosuna eklenir.
Trigger enable/disable yapma
Enable (Aktifleştirme):
1 2 3 4 5 6 7 |
--yöntem 1 disable trigger trigger_adı On tablo_adı --yöntem 2 alter table tablo_adı disable trigger trigger_adı |
Disable (Pasifleştirme):
1 2 3 4 5 6 7 |
--Yöntem 1 enable trigger trigger_adı On tablo_adı --Yöntem 2 alter table tablo_adı enable trigger trigger_adı |
Tüm Triggerları Pasifleştirme / Aktifleştirme
1 2 3 4 5 |
enable trigger all On tablo_adı disable trigger all On tablo_adı |
Trigger Kaldırma
Kaldırma :
1 2 3 |
drop trigger trigger_adı |
After /Instead Of Kavramı
After Triggerler: Insert,Update yada Delete işlemi gerçekleştirildiğinde tetiklenir. Sadece tablolar için tanımlanabilir.
Instead Of Triggerler: Belirlenen işlem gerçekleşirken devreye girip, SQL sorgusu yerine çalıştırılır. After tetikleyicileri sadece tablolar için tanımlanabilirken Instead Of tetikleyicileri hem tablolar için hem de view tabloları ile de kullanılabilir.
Rollback Transaction ve Raise Error
Rollback Transaction komutu trigger ne için tanımlanmışsa o işlemi iptal etmek için kullanılır.
Raise Error komutu kullanıcıya işlemin neden iptal edildiğini bildirmek için kullanılır. Kullanıcıyı bilgilendirme amacı ile kullanılır.
Sql Server Management Trigger Nerede Bulunur
Sql Server Management üzerinde triggerlar aşağıdaki resimde görüntülendiği gibi ilgili tabloya tıklandığında tablonun altında görünecektir.
Aşağıdaki Komutlar Trigger İçine Kullanılmaz
Alter Database Create Database
Load Database Drop Database
Disk Init Disk Resize
Load Log Reconfigure
Restore Database Restore Log
Recursive Trigger Oluşturma
Trigger’ın kendini çağırması durumudur.
Triggerda aynı tabloda işlem yapılıyorsa o işlem sonucu aynı trigger bir daha çalışabilir.
Trigger başka tabloda işlem yapar. O işlem sonucu çalışan başka bir triggerda yeniden birinci tablo ile ilgili işlem yapar. Bu durum da da recursive olur.
32 tane en fazla çalışır.
Sürekli bir şart ile kontrol edilip sonlandırılmalıdır. Yoksa sonsuz döngüye girer.
1 2 3 4 5 |
Alter database ticaret set recursive_triggers on sp_dpoption ticaret,'recursive triggers',true |
Recursive trigger’ları aktif yapmak için yukarıdaki kodlar kullanılır.
Bir alanının güncellendiğini öğrenmek için update(alanadi) fonksiyonu kullanılır. Sonucu true yada false olarak döner.
Bir trigger başka bir tabloda işlem yaparken o tablodaki trigger’ı da çalıştırabilir.
İç içe 32 trigger çalıştırılabilir.
@@Nestlevel hangi seviyede olduğunu belirtir.
Sp_configure procedure’ü kullanılarak iç içe tetiklenme kapatılabilir.
İlk trigger çalışır diğerleri tetiklenmez.
Trigger Örnekleri
Trigger örneklerini basit olarak oluşturulmuş kütüphane veritabanı üzerinde uygulayacağım. Kütüphane veritabanını indirmek için tıklayın.
Aşağıdaki örneklerde triggerlar bir kez execute ile yürütüldükten sonra insert/update/delete işlemleri gerçekleştirildiğinde ilgili trigger tetiklenecektir.
Bazı örneklerde triggerlar bir birlerini etkileyeceği için ya triggerı kaldırmanız yada bir birini etkileyeceğini düşündüğünüz triggerları durdurmanız gerekir.
Örnek: Kullanıcı bir kayıt ekledikten sonra ogrenci tablosunu listeleyen trigger oluşturunuz.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
--trigger kodu create trigger trg_Listele on ogrenci after insert as begin select * from ogrenci end --Kayıt ekleme örneği insert into ogrenci(ograd,ogrsoyad,cinsiyet,dtarih,sinif,puan)values('Ali','Veli','E',GETDATE(),'10A',0) --ÖNCE TRİGGER I ÇALIŞTIR |
Örnek: 10A sınıfına cinsiyeti kız olan öğrenciler kaydedilebilsin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Create trigger cinsiyet on ogrenci for insert As if(exists(Select * from inserted where sinif = '10A' and cinsiyet = 'E')) Begin raiserror('10A sınıfına erkek öğrenci kaydedilemez',1,1) rollback transaction End --Kayıt ekleme test insert into ogrenci(ograd,ogrsoyad,cinsiyet,dtarih,sinif,puan)values('Ali','Veli','E',GETDATE(),'10A',0) --ÖNCE TRİGGER I ÇALIŞTIR |
Örnek: 10A’nın kız öğrencileri silinemesin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Create trigger trg_10AKizOgrenciSilme on ogrenci after delete as begin if(exists(select * from deleted where cinsiyet='K' and sinif='10A')) begin raiserror('10A sınıfındaki kız öğrencileri silemezsiniz!!',0,0) rollback transaction end end delete from ogrenci where cinsiyet='K' and sinif='10A' --kullanadan önce triggerı çalıştırmayı unutmayın |
Örnek: Silinen öğrenciler başka bir tabloya kaydedilsin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
--silinen öğrencinin adını soyadını mezun tablosuna kaydediyoruz. create table mezun(ograd varchar(50),ogrsoyad varchar(50)) create trigger trg_SilineniEkle on ogrenci after delete as begin insert into mezun select ograd,ogrsoyad from deleted end delete from ogrenci where ogrno=3 --triggerı test ediyoruz select * from mezun |
Örnek: Öğrencilerin cinsiyet alanı güncellenmesin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
create trigger trg_Guncelle on ogrenci after update as begin --if(update(cinsiyet)) if(exists(select * from inserted,deleted where inserted.ogrno=deleted.ogrno and inserted.cinsiyet!=deleted.cinsiyet)) --Exists içindeki değerin olup olmadığına bakar. begin raiserror('Cinsiyet Güncellenemez.',1,1) rollback transaction end end --trigger test edilmesi select * from ogrenci where ogrno = 5 update ogrenci set cinsiyet = 'E' where ogrno=5 |
Örnek: Kitap tablosu güncellenirken eski sayfa sayısı yeni sayfa sayısından fazla olmak zorunda
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
create trigger kitapguncelle on kitap after update as begin if(exists(select * from inserted,deleted where inserted.sayfasayisi=deleted.sayfasayisi or inserted.sayfasayisi > deleted.sayfasayisi)) begin raiserror('Eski sayfa sayısı yeni sayfa sayısından fazla olmak zorunda',1,1) rollback transaction end end --Birinci Kontrol update kitap set puan=20, sayfasayisi=150 where kitapno=1 select * from kitap where kitapno=1 --İkinci Kontrol update kitap set puan=20, sayfasayisi=170 where kitapno=1 select * from kitap where kitapno=1 |
Örnek: Tür tablosundan hiçbir kayıt silinmesin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Create Trigger trg_TurSilinmez on tur after delete as begin raiserror('tur Tablosu üzerinde kayıt silinmez',1,1) rollback transaction end delete from tur select * from tur |
After yerine Instead of kullanılarak delete işlemi yapmak yerine hata vermesi sağlanabilir.
1 2 3 4 5 6 7 8 9 |
Create Trigger trg_TurSilinmez on tur instead of delete as begin raiserror('tur Tablosu üzerinde kayıt silinmez',1,1) rollback transaction end |
Örnek: Ogrenci tablosuna silindi isminde bir alan ekleyiniz. Ogrenci silinmesin silindi alanının değeri 1 olsun –instead of kullanılacak after yerine
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Alter Table ogrenci add silindi bit null Create trigger ogrenciSil on ogrenci instead of delete as begin update ogrenci set silindi=1 where ogrno in (select ogrno from deleted) end --triggerı çalıştırmayı unutmayın. daha önce oluşturulan triggerlar ile çakışmaması için eskilerini durdurmayı unutmayın delete from ogrenci where ogrno in(8,9) select * from ogrenci where ogrno in (8,9) |
Örnek: Tur tablosuna gTarih adında bi alan ekleyin tur tablosunda guncelleme yapıldığında gtarih alanına güncelleme tarihini kaydediniz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Alter Table tur add gTarih datetime null Create Trigger turGuncelle on tur after update as begin --if(not update(guncellendi))--recursive trigger açıksa hata verememesi için update tur set gTarih=GETDATE() where turno in (select turno from deleted) end update tur set turadi='Başka Bir Tür'where turno=3 select * from tur where turno=3 |
Örnek: 500 sayfadan daha az roman türünde kitap eklenemesin
1 2 3 4 5 6 7 8 9 10 11 |
Create trigger kitap1 on kitap after insert as if(exists(Select * from inserted,tur where inserted.turno = tur.turno and turadi='roman' and sayfasayisi<500)) begin raiserror('500 sayfadan az roman türünde kitap kaydedilemez',1,1); rollback transaction End |
Ben C#la hazırladığım programın database ni sql serverle bağladım şimdi c# da bisiklet kiralama ve teslim işlemi yaptığım formum var kiralama ekranımda KiraId KiralayanKisiId KiralanaBisikletId KiralananIstasyonId
TeslimTarihi TeslimSaati TeslimAlınaGorevliId bölümleri mevcut teslim formumda da KiraId TeslimTarihi TeslimSaati IadeTarihi IadeSaati IadeEdilenGorevliId KiralamaSüresi KiraUcreti ve bu 2 form aynı tablo üzerinde işlem yapıyor ve benim sorum da TeslimAlınaGorevliId ile IadeEdilenGorevliId aynı değil ise bisikletin zimmetli oldugu istasyon değişicek
zimmet tablom görevli tablom bisiklet tablom İstasyon tablom da var bunlarda bir birleriyle ilişkili bu sorumu triggerla yazmak istiyorum ama bunun için tanımladıgım değişkenlere sorgularla atamalar yapıp koşulu ssağlarsa zimmet ekranında güncelleme gerçekleşecek bunla ilgili fikirleri niz nedir
Teşekkürler
Disable devre dısı bırakmak demektir, dolayısıyla triggeri pasiflestirirken Enable degıl Disable kullanırız, tam tersidir.
[…] https://www.yazilimbilisim.net/veritabani/mssql/sql-serverda-trigger-kullanimi/ […]
hocam “raiserror” da ifadeden sonra girdğimiz sayılar neye göre değişiyor.
“raiserror(‘tur Tablosu üzerinde kayıt silinmez’,1,1)” mesela burada neden 1,1 de 0,0 değil ?
Hata mesajları konusu sql serverda uzun bir konu. Ama yinde özet olması bakımından birşeyler yazayım. Sql Server üzerinde hata mesajları üç parça halinde belirtilmektedir. Msg,level ve state olarak ifade ediliyor. Msg kodu hatanın sql server tarafından belirtilen kod numarasıdır. msg:50000 Kullanıcı tanımlı hataları ifade etmek için kullanılır. Level ise hatanın seviyesini belirtmek için kullanılıyor. Yanılmıyorsam 25’e kadar değer alabiliyordu. Son olarak da hata ile ilgili durum(state) belirtmek için de state değeri veriliyor. Bir hata grubu içinde farklı durumlar olabilir. Bunları gruplandırmak için kullanılıyor. Şuana kadar kullanmadım ama bir ara inceleyip konu ile ilgili yazı yazmak isterim.
Özetle 1den fazla hata verdireceksen her hata için 1,1 yerine seviye ve durum değerlerini değiştirerek program tarafında hatayı numarası ile belirtme şansına sahip olursun.
Teşekkürler iyi çalışmalar
“Örnek: Kitap tablosu güncellenirken eski sayfa sayısı yeni sayfa sayısından fazla olmak zorunda.”
Hocam bu soruda
inserted.sayfasayisi=deleted.sayfasayisi AND inserted.sayfasayisi > deleted.sayfasayisi))
AND yerine OR olması gerekmiyor mu?
Kolay gelsin iyi çalışmalar
Örneği hazırlarken dikkatimden kaçmış haklısın or olması gerekiyor. Dikkatiniz için teşekkür ederim.
Rica ederim. Teşekkürler. İyi çalışmalar
inserted.sayfasayisi >= deleted.sayfasayisi desek olur mu?
Aynı değerin girilmesi durumu da kontrol edilecekse neden olmasın.