Oracle Pl/Sql'de Insert, Update, Delete Trigger Oluşturma ve Kullanımı

'Marksman

Kadim Üye
8 Ocak 2013
5,400
2
Merhaba, Oracle pl/sql ile trigger kullanımı inceleyelim. Öncelikle trigger nedir ne işe yarar buna bir göz atalım. Trigger(tetkikleyici) sistem tarafından belirli durumlarda otomatik olarak çalıştırılan bir programdır. Neden bir triggera ihtiyaç duyarız ? Örnek olarak tabloya bir kayıt eklediğimizde otomatik olarak kayıt tarihi olarak sistem tarihinin atması ya da tabloda bir güncelleme veya silme yaptığımızda ilgili kayıt için başka bir tabloya log kaydı atması gibi çeşitli sebepler ve kontroller için triggerlara ihtiaç duyarız. Tablolarda yaptığımız "insert , update , delete" işlemlerinde trigger çalışır ve bu çalışma "before , after" olmak üzere ikiye ayrılır. Before zamanında çalışan trigger bizim yaptığımız işlemden önce devreye girer ve ilgili trigger içine yazdığımız kontrol kodlarını ya da programı çalıştırır. After zamanında çalışan trigger ise tabloya yaptığımız işlemden sonra devreye girer ve içinde bulunan kontrolleri çalıştırır. Trigger(lar)'ın çalışma zamanlarını ve işlemleri daha iyi anlamak için örneklerimize bir göz atalım. Öncelikle triggerlarımızı yazacağımız ve kontrolleri test edeceğimiz bir tabloya ihtiyacımız var ve hemen bu tabloyu oluşturalım. Trigger içerisinde bu tablo ile ilgili işlem yaparken sequence kullanacağımız için tablodan hemen sonra sequence imizi de yaratalım.
Kod:
create table ORNEKTABLO
(
**kayitid** NUMBER,
**aciklama* VARCHAR2(250),
**kayittar* DATE,
**gunceltar DATE
);
Kod:
create sequence ORNEKTABLO_SEQ
minvalue 0
maxvalue 999999999
start with 1
increment by 1
nocache;
Bu tablomuzun üzerine sırası ile before ve after zamanında çalışacak insert, update, delete triggerlarımız yazacağız. Trigger oluştuktan sonra her birisinin içerisine ilgili zamanda çalışacak olan kontrol kodlarımızı yazağız. Birinci senaryomuz : Tabloya bir kayıt attığımızda tablodaki "kayitid" alanına sequence dan sıradaki değeri alıp ve "kayittar" alanına da günün tarihini ekleyen basit bir kontrol için insert işleminin before zamanında çalışacak olan bir trigger yazalım.
Kod:
create or replace trigger ornektablo_before_ins
  before insert on ornektablo
  for each row
declare
  
--lokal değişkenler tanımlanır.
begin
 
  if :new.kayitid is null then
    select ornektablo_seq.nextval into :new.kayitid from dual;
  end if;
 
  :new.kayittar := sysdate;
 
end ornektablo_before_ins;
Yukarıdaki kod bloğunda yazılı olan "before insert on ornektablo" tanımlaması hazırladığımız triggerın hangi tablo üzerinde, hangi işlem sırasında ve hangi zamanda çalışağını belirtmek için kullanılır. Ayrıca kod bloğunda görülen ":new" belirteci ise tabloya insert anında gelen ilgili kolon içeriğini belirtir. Şimdi yazığımız kodların çalışmasını test edelim. Tablomuza bir kayıt insert edelim ve bu işlem sırasında triggerda yazığımız konrtollerin çalışıp tabloyadaki "kayitid" alanına sequence deki sıradaki değeri ve "kayittar" alanına da günün tarihini atıp atmadığına bakalım. Bu işlem için aşağıdaki insert sqlini kullanabiliriz.
Kod:
insert into ornektablo
  (kayitid, aciklama, kayittar, gunceltar)
values
  (null, 'Tabloya Kayıt Ekleme:Before', null, null);
commit;
Yukarıdaki sqlde de görüldüğü gibi sadece "aciklama" alanına değer ekliyoruz. Diğer atamalar trigger ile yapılacak. Bu kod çalıştıktan sonra tabloyu sorgulayıp sonucu görelim.
Kod:
select * from ornektablo;
K.ID ACIKLAMA K.TAR G.TAR
1 Tabloya Kayıt Ekleme:Before 13.05.2013 20:07:01
Sorgu sonucunda da görüldüğü gibi tabloya insert işleminin before aşamasında yazdığımız kontroller çalışarak bizim null olarak atama yaptığımız alanlara ilgili değerleri ekledi. Bu şekilde birinci senaryomuzu tamamlamış olduk. İkinci senaryomuz : Birinci senaryoda tabloya eklediğimiz kayıdın "aciklama" alanındaki değerini güncelleyelim ve bu güncellemeden önce çalışması için ilgili tablo için update işleminin before zamanında çalışacak bir trigger hazırlayalım. Bu arada yaptığımız update işlemin bir yedeği olması için güncellemden önceki kaydın durumunu bir log tablosuna atalım. Bu işlemide trigger içinde yapalım ve log tablomuzu ardından da "logid" için kullanacağımız sequence imizi yaratalım.
Kod:
create table ORNEKTABLO_LOG
(
  logid       NUMBER,
  logaciklama VARCHAR2(250),
  logtarih    DATE,
  kayitid     NUMBER,
  aciklama    VARCHAR2(250),
  kayittar    DATE,
  gunceltar   DATE
);
Kod:
create sequence ORNEKTABLO_LOG_SEQ
minvalue 0
maxvalue 999999999
start with 1
increment by 1
nocache;
Tablo ve sequence hazır olduğuna göre triggerımızı hazırlayalım ve senaryomuzu test edelim.
Kod:
create or replace trigger ornektablo_before_upd
  before update on ornektablo
  for each row
declare
  logid number;
begin
  :new.gunceltar := sysdate;
 
  select ornektablo_log_seq.nextval into logid from dual;
 
  insert into ornektablo_log
    (logid, logaciklama, logtarih, kayitid, aciklama, kayittar, gunceltar)
  values
    (logid, 'BeforeUpdate', sysdate, :old.kayitid, :old.aciklama, :old.kayittar, :old.gunceltar);
 
end ornektablo_before_upd;
Yukarıdaki kod bloğunda yazılı olan "before update on ornektablo" tanımlaması aynı şekilde insert işleminde kullanılan trigger gibi hazırladığmız triggerın hangi zaman ve durumda çalışacağını belirtir. Ayrıca kod bloğunda görülen ":eek:ld" belirteci ise tabloya update işleminden önce ilgili kolonun değerini gösterir. Bunu daha iyi görmek için update işleminden sonra tabloya ve log tablosuna sorgu atıp görebiliriz.
Kod:
update ornektablo
   set aciklama = 'Tabloyu Güncelleme:Before'
 where kayitid = 1;
commit;
Artık update işlemi yapıldığına göre tablonun son durumuna ve log tablosundaki kayıt durumuna bakabiliriz.

Kod:
select * from  ornektablo;
Kod:
Tabloyu Güncelleme:Before	13.05.2013 20:07:01	13.05.2013 20:25:08
Kod:
select * from  ornektablo_log;

1 BeforeUpdate 13.05.2013 20:25:08 1 Tabloyu Güncelleme:Before 13.05.2013 20:07:01 13.05.2013 20:24:11
İki tablonun sorgu sonuçlarında da görüldüğü gibi triggerımız istediğimiz gibi çalışmış ve bizim yerimize otomatik olarak log tablosuna kayıt atıp aynı zamanda mevcut tablo üzerindeki "gunceltar" alanınada güncelleme tarihi olarak günün tarihini atmış. Bu sonuç ile de ikinci senaryomuzu tamamlamış olduk. Üçüncü senaryomuz : Birinci ve ikinci senaryoda tabloya ekleyip ve güncelledimiz kaydı silelim ve bu silme işleminden önce çalışması için ilgli işlemin before zamanında çalışacak bir trigger hazırlayalım.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
create or replace trigger ornektablo_before_del
before delete on ornektablo
for each row
declare
logid number;
begin

select ornektablo_log_seq.nextval into logid from dual;

insert into ornektablo_log
(logid, logaciklama, logtarih, kayitid, aciklama, kayittar, gunceltar)
values
(logid, 'BeforeDelete', sysdate, :eek:ld.kayitid, :eek:ld.aciklama, :eek:ld.kayittar, :eek:ld.gunceltar);

end ornektablo_before_del;
Triggerımız hazır. Kod bloğunda görülen "before delete on ornektablo" komutu diğer trigger tanımlamalarında açıkladığım gibi bu trigger hangi tabloda ve hangi durum ve zamanda çalışacağını belirtiyor. Şimdi tablomuzda kaydı silelim ve triggerın çalışmasını görelim.
?
1
2
3
delete ornektablo
where kayitid = 1;
commit;
?
1
select * from ornektablo;
Sorgusu ile tabloyu sorguladığımızda hiç kayıt gelmeyecektir ve log tablosunu sorguladığımızda ise kayıtları görebiliriz.
?
1
select * from ornektablo_log;
L.ID L.ACIKLAMA L.TARIH K.ID ACIKLAMA K.TAR G.TAR
1 BeforeUpdate 13.05.2013 20:25:08 1 Tabloyu Güncelleme:Before 13.05.2013 20:07:01 13.05.2013 20:24:11
2 BeforeDelete 13.05.2013 20:38:31 1 Tabloyu Güncelleme:Before 13.05.2013 20:07:01 13.05.2013 20:25:08
Log tablomuz "logid" 2 olan kayıt atıldıktan sonra ana tablodaki kayıt silinmiştir. Bu sonuçlarıda gördüğüze göre üçüncü senaryomuzu da tamamlamış olduk. İlk üç senaryomuz için hep before zamanında çalışacak olan triggerları hazırladık ve testini yaptık. Aynı şekilde şimdide after zamanında çalışacak olan triggerlarımız hazırlayalım ve testlerimizi yapalım. Artık elimizde bir tablomuz ve hareketlerin detayını tuttuğumuz bir log tablomuz olduğundan yeni bir tablo yaratmadan mevut tablo üzerinde işlem yapıp after triggerının çalışmasını kontrol edeceğiz. Dördüncü senaryomuz : Birinci senaryomuzda insert işlemi yaptığmız şekilde tabloya insert işleminden sonra log tablosuna bu durum hakkında bir kayıt atalım. Bunun için tablonun insert işleminin after zamanına bir trigger yazalım.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
create or replace trigger ornektablo_after_ins
after insert on ornektablo
for each row
declare
logid number;
begin

select ornektablo_log_seq.nextval into logid from dual;

insert into ornektablo_log
(logid, logaciklama, logtarih, kayitid, aciklama, kayittar, gunceltar)
values
(logid, 'AfterInsert', sysdate, :new.kayitid, :new.aciklama, :new.kayittar, :new.gunceltar);

end ornektablo_after_ins;
Trigger hazır olduğuna göre şimdi tabloya yeni bir kayıt ekleyip after işleminde log tablosuna atılan kaydı kontrol edelim.
?
1
2
3
4
5
insert into ornektablo
(kayitid, aciklama, kayittar, gunceltar)
values
(null, 'Tabloya Kayıt Ekleme:After', null, null);
commit;
?
1
select * from ornektablo;
K.ID ACIKLAMA K.TAR G.TAR
2 Tabloya Kayıt Ekleme:After 13.05.2013 20:53:03
?
1
select * from ornektablo_log;
L.ID L.ACIKLAMA L.TARIH K.ID ACIKLAMA K.TAR G.TAR
1 BeforeUpdate 13.05.2013 20:25:08 1 Tabloyu Güncelleme:Before 13.05.2013 20:07:01 13.05.2013 20:24:11
2 BeforeDelete 13.05.2013 20:38:31 1 Tabloyu Güncelleme:Before 13.05.2013 20:07:01 13.05.2013 20:25:08
3 AfterInsert 13.05.2013 20:53:03 2 Tabloya Kayıt Ekleme:After 13.05.2013 20:53:03
Tablo sorgularında da görüldüğü gibi insert işleminin hemen ardından log tablosuna ilgili kayıt triggerdaki kod sayesinde eklenmiştir.Bu durumda dördüncü senaryomuzu da tamamlamış olduk. Beşinci senaryomuz : İkinci senaryomuzda update işlemi yaptığmız şekilde tabloya update işleminden sonra log tablosuna bu durum hakkında bir kayıt atalım. Bunun için tablonun update işleminin after zamanına bir trigger yazalım.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
create or replace trigger ornektablo_after_upd
after update on ornektablo
for each row
declare
logid number;
begin

select ornektablo_log_seq.nextval into logid from dual;

insert into ornektablo_log
(logid, logaciklama, logtarih, kayitid, aciklama, kayittar, gunceltar)
values
(logid, 'AfterUpdate', sysdate, :new.kayitid, :new.aciklama, :new.kayittar, :new.gunceltar);

end ornektablo_after_upd;
Trigger hazır olduğuna göre şimdi tablomuzdaki "kayitid" değeri 2 olan kaydımızı güncelleyelim ve after işleminde log tablosuna atılan kaydı kontrol edelim.
?
1
2
3
4
update ornektablo
set aciklama = 'Tabloyu Güncelleme:After'
where kayitid = 2;
commit;
?
1
select * from ornektablo;
K.ID ACIKLAMA K.TAR G.TAR
2 Tabloyu Güncelleme:After 13.05.2013 20:53:03 13.05.2013 21:04:26
?
1
select * from ornektablo_log;
L.ID L.ACIKLAMA L.TARIH K.ID ACIKLAMA K.TAR G.TAR
1 BeforeUpdate 13.05.2013 20:25:08 1 Tabloyu Güncelleme:Before 13.05.2013 20:07:01 13.05.2013 20:24:11
4 BeforeUpdate 13.05.2013 21:04:26 2 Tabloya Kayıt Ekleme:After 13.05.2013 20:53:03
2 BeforeDelete 13.05.2013 20:38:31 1 Tabloyu Güncelleme:Before 13.05.2013 20:07:01 13.05.2013 20:25:08
3 AfterInsert 13.05.2013 20:53:03 2 Tabloya Kayıt Ekleme:After 13.05.2013 20:53:03
5 AfterUpdate 13.05.2013 21:04:26 2 Tabloyu Güncelleme:After 13.05.2013 20:53:03 13.05.2013 21:04:26
Tabi tablomuzda önceki triggerlarda aktif olduğundan before aşamasındaki kontrollerde çalışıp log tablosuna kayıt atmış. Bu sonuçlarınıda gördüğümüze göre beşinci senaryomuzu da tamamlamış olduk. Altıncı senaryomuz : Üçüncü senaryomuzda silme işlemi yaptığmız şekilde tablomuzdaki "kayitid" 2 değerine sahip kaydımızı silelim ve silme işleminden sonra log tablosuna bu durum hakkında bir kayıt atalım. Bunun için tablonun delete işleminin after zamanına bir trigger yazalım.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
create or replace trigger ornektablo_after_del
after delete on ornektablo
for each row
declare
logid number;
begin

select ornektablo_log_seq.nextval into logid from dual;

insert into ornektablo_log
(logid, logaciklama, logtarih, kayitid, aciklama, kayittar, gunceltar)
values
(logid, 'AfterDelete', sysdate, :eek:ld.kayitid, :eek:ld.aciklama, :eek:ld.kayittar, :eek:ld.gunceltar);

end ornektablo_after_del;
Trigger hazır olduğuna göre şimdi tablodaki kaydımızı silip after işleminde log tablosuna atılan kaydı kontrol edelim.
?
1
2
3
delete ornektablo
where kayitid = 2;
commit;
?
1
select * from ornektablo;
Silme işleminden sonra tablomuzda kayıt olmadığından bu sorgudan sonuç gelmeyecektir. Fakat log tablosuna atılan kaydı görebiliriz.
?
1
select * from ornektablo_log;
L.ID L.ACIKLAMA L.TARIH K.ID ACIKLAMA K.TAR G.TAR
1 BeforeUpdate 13.05.2013 20:25:08 1 Tabloyu Güncelleme:Before 13.05.2013 20:07:01 13.05.2013 20:24:11
4 BeforeUpdate 13.05.2013 21:04:26 2 Tabloya Kayıt Ekleme:After 13.05.2013 20:53:03
2 BeforeDelete 13.05.2013 20:38:31 1 Tabloyu Güncelleme:Before 13.05.2013 20:07:01 13.05.2013 20:25:08
3 AfterInsert 13.05.2013 20:53:03 2 Tabloya Kayıt Ekleme:After 13.05.2013 20:53:03
5 AfterUpdate 13.05.2013 21:04:26 2 Tabloyu Güncelleme:After 13.05.2013 20:53:03 13.05.2013 21:04:26
6 BeforeDelete 13.05.2013 21:10:34 2 Tabloyu Güncelleme:After 13.05.2013 20:53:03 13.05.2013 21:04:26
7 AfterDelete 13.05.2013 21:10:34 2 Tabloyu Güncelleme:After 13.05.2013 20:53:03 13.05.2013 21:04:26
Tablomuzda son durumuda gördüğümüze göre silme işleminde de after triggerının doğru olarak çalıştığını görülmektedir. Bu durumda altıncı senaryomuzu da tamamlamış olduk. Konuyu toparlayacak olursak, trigger sistem tarafından otomatik olarak çalıştırılan ve bizim içersine yazdığımız kodlardan oluşan bir mekanizmadır. Bir tablo üzerine 6 (altı) durum için trigger yazabiliriz. Bunlar sırasıyla "before insert", "after insert", "before update", "after update", "before delete", "after delete" olarak belirtilebilinir. Her durum için yukarıda bir şablon trigger hazırladık ve kullandık. Bu kullanım ihtiyaçlara göre değişiklik gösterebilir. Bu makalenin sonunda trigger nedir sorusunun cevabını ve kullanımını öğrenmiş olduk.
NOT: ornektablo tablosundaki alanlar tablo görselinde yer kazanamak için isimleri aşağıdaki gibi değiştirilmiştir;
KAYITID = K.ID
ACIKLAMA = ACIKLAMA
KAYITTAR = K.TAR
GUNCELTAR = G.TAR
ornektablo_log tablosundaki alanlar da aşağıdaki gibi değiştirilmiştir;
LOGID = L.ID
LOGACIKLAMA = L.ACIKLAMA
LOGTARIH = L.TARIH
KAYITID = K.ID
ACIKLAMA = ACIKLAMA
KAYITTAR = K.TAR
GUNCELTAR = G.TAR
Kolay gelsin.
 
Son düzenleme:
Üst

Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.