Trigger
Tablo ve veri tabanı triggerları vardır
tablo triggerları insert update delete öncesinde veya sonrasında devreye giren mekanizma örneğin aralarında link bulunan iki VT’den birindeki x tablasuna insert edildiğinde aynı verinin y tablosuna da geçmesi isteniyorsa burada trigger kullanılabilir. (insert trigger -before insert after insert )
Bir tabloya mesai saatleri dışında değişiklik yapılması istenmiyorsa o tabloya mesai saatlerini kontrol eden bir trigger konulabilir.
statement level trigger ; insert statementı yapılıyorsa o statement için çalışan trigger. (bu saatte insert edemesin vb.)
row level trigger ; Tablodaki her satır için çalışır. Değiştirilen herseyin başka bir yerde de değiştirilmesi gerekiyorsa kullanılır. Etkilenen her satır için.
instead of trigger ; view üzerinden update etmek istenirse , iot ile bu view a update yapılmak istenirse git şurları güncelle
gibi istekler olursa kullanılır çok fazla bir kullanım alanı yoktur
örnek : mesai saatleri dışında employees tablosunda delete/update/insert yapılması istenmiyorsa
|
1 2 3 4 5 6 7 8 9 10 11 12 |
create or replace trigger security_time_check before insert or update or delete on emp --before update of salary on emp şeklinde de tanımlama yapılabilir. declare gun varchar2(3); saat number(2); begin gun := to_char(sysdate, 'DY', 'NLS_DATE_LANGUAGE=TURKISH'); saat := to_number(to_char(sysdate, 'fmHH24')); if (gun = 'CMT' OR gun = 'PAZ') OR (saat not between 8 and 17) then raise_application_error(-20100, 'Mesai saatleri dışında değişiklik yapamazsınız'); end if ; end; |
Disable etmek için
|
1 |
alter trigger security_time_check disable ; |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
create or replace trigger security_time_check before insert or update or delete on emp declare gun varchar2(3); saat number(2); begin gun := to_char(sysdate, 'DY', 'NLS_DATE_LANGUAGE=TURKISH'); saat := to_number(to_char(sysdate, 'fmHH24')); if (gun = 'CMT' OR gun = 'PAZ') OR (saat not between 8 and 17) then if inserting then raise_application_error(-20100, 'Mesai saatleri dışında emp de insert yasak'); elsif updating then raise_application_error(-20100, 'Mesai saatleri dışında emp de update yasak'); else raise_application_error(-20100, 'Mesai saatleri dışında emp de delete yasak'); end if; end if ; end; |
Row LEvel Triggers
for each row : tüm tablo için değil her satır için çalışıyor.
Örnekmaaş update edilirken ortalama maaşın altında olmasın.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
create or replace trigger ort_maasdan_buyuk_olmali before insert or update or delete of salary on emp for each row declare ort_maas number ; begin select round(avg(salary)) into ort_maas from emp ; if :new.salary < ort_maas then -- yeni maas raise_application_error(-20100, 'Maasin yeni degeri Ortalama maasdan('||ort_maas||') kucuk olamaz'); end if ; end; |
satir bazin calistigi icin ortalama maaşı bulamıyor.
log tablosu
|
1 2 3 4 5 6 7 8 9 10 |
create table emp_log_tablo ( kullanici varchar2(20), tarihsaat date, tablo_adi varchar2(30), islem varchar2(10), employees_id number, eski_maas number, yeni_maas number ) |
|
1 2 3 4 5 6 7 8 9 10 11 |
create or replace trigger trg_emp_maas_log after update of salary on emp for each row declare begin INSERT INTO HR.EMP_LOG_TABLO ( KULLANICI, TARIHSAAT, TABLO_ADI, ISLEM, EMPLOYEES_ID, ESKI_MAAS, YENI_MAAS) VALUES (user ,sysdate ,'employees' ,'update',:new.employee_id , :old.salary , :new.salary ); end; |
tablo olustur
|
1 2 3 4 5 6 |
create table musteri ( no number primary key, ad varchar2(20), soyad varchar2(20) ) |
squence olustur
|
1 2 3 |
create sequence seq_musteri ; insert into musteri values (seq_musteri.nextval,'Musteri1', 'Soyad1') |
trigger olustur
|
1 2 3 4 5 6 7 8 9 |
create or replace trigger trg_bef_ins_musteri before insert on musteri for each row declare begin select seq_musteri.nextval into :new.no from dual; end; |
test edilir
|
1 2 |
insert into musteri(ad, soyad) values ('Deneme', 'Yanilma') |
new ve old kelimelerini yalnızca for each row için kullanabiliriz yani row level de kullanabiliriz. statement level de kullanamayız.
Auto increment bir alan isteniyorsa en iyi çözüm sequence + trigger dır. Kimin hangi tarihte insert ettiğini loglamak için.
tablo olustur
|
1 2 3 4 5 6 |
create table musteri_log ( kullanici varchar2(20), islem varchar2(10), tarihsaat date ) |
procedure olustur
|
1 2 3 4 5 6 |
create or replace procedure proc_musteri_logla (kullanici varchar2, islem varchar2) as begin insert into musteri_log values(kullanici, islem, sysdate); end; |
trigger olustur
|
1 2 3 4 5 6 7 |
create or replace trigger trg_after_ins_musteri after insert on musteri for each row declare begin proc_musteri_logla(user, 'insert'); end; |
2. alternatif
|
1 2 3 |
create or replace trigger trg_after_ins_musteri_1 after insert on musteri call proc_musteri_logla(user,'insert') |
not : begin end olursa call olmayacak
test edilir
|
1 2 |
insert into musteri (ad, soyad) values ('test', 'deneme') |
|
1 2 |
alter trigger trg_after_ins_musteri compile alter trigger trg_after_ins_musteri disable/enable |
yeni VT’ lerde long alanlar clob olarak tutuluyor. long (2GB tutar) karakter tutar en önemli fark clobla (4GB tutar)
long alan içinde text araması yapılamaz
örnek
|
1 2 3 4 5 |
create table yazi1 ( no number, yazi long ); |
|
1 2 3 4 5 |
create table yazi2 ( no number, yazi clob ); |
|
1 2 |
insert into yazi1 values(1,'test test') insert into yazi2 values(1,'test test') |
|
1 |
select * from yazi1 where yazi like '%test%' |
Bu sorgu yazi2 için sonuç dönderir ama yazi1 de hata verir.
type… table
index by table diye tanımlanıyor. Binary integer veya PLS_integer , PLS daha hızlı oldugundan tercih ediliyor.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
declare type sayi_listesi is table of number index by pls_integer; sayilar sayi_listesi; begin FOR i IN 1 .. 6 LOOP sayilar(i) := i + 5; END LOOP; FOR i IN sayilar.first..sayilar.last LOOP dbms_output.put_line(sayilar(i)); END LOOP; end; |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
declare type sayi_listesi is table of number index by pls_integer; sayilar sayi_listesi; begin FOR i IN 1 .. 6 LOOP sayilar(i) := i + 5; END LOOP; FOR i IN sayilar.first..sayilar.last LOOP dbms_output.put_line(sayilar(i)); END LOOP; dbms_output.put_line('sayi:'||sayilar.count); end; |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
declare type sayi_listesi is table of number index by pls_integer; sayilar sayi_listesi; begin FOR i IN 1 .. 6 LOOP sayilar(i) := i + 5; END LOOP; FOR i IN sayilar.first..sayilar.last LOOP dbms_output.put_line(sayilar(i)); END LOOP; dbms_output.put_line('sayi:'||sayilar.count); if (sayilar.exists(6)) then dbms_output.put_line('6. eleman var.'); end if; end; |
