1 觸發(fā)器簡介
? 1) 觸發(fā)事件
? 2) 觸發(fā)條件
? 3) 觸發(fā)操作
???? . 觸發(fā)器代碼的大小不能超過32k,如果使用大量代碼建立觸發(fā)器,應該先建立存儲過程,然后再觸發(fā)器中使用call語句調(diào)用存儲過程。
???? . 觸發(fā)器中正能含有select ,insert,update 和delete 語句,而不能含有ddl 語句,和事物控制語句。
2 建立dml 觸發(fā)器
?1) 觸發(fā)時機
? before,after 表示在執(zhí)行dml操作之后觸發(fā)器
?2)觸發(fā)事件
? insert ,update 和delete 操作。也可以使用書法事件
?3) dml 觸發(fā)器是針對特定表進行的 因此必須制定dml 操作所對應的表
?4) 觸發(fā)器類型 用于指定當觸發(fā)器事件之后,需要執(zhí)行幾次觸發(fā)器操作。如果指定語句觸發(fā)器類型
那么會執(zhí)行一次觸發(fā)器代碼:如果指定行觸發(fā)器類型,則會在每個被作用行上執(zhí)行一次觸發(fā)器代碼。
?5) 觸發(fā)條件
?用于指定執(zhí)行行觸發(fā)器代碼的條件,只有為ture時,才會執(zhí)行行觸發(fā)器代碼。
? 6) 如果使用pl/sql 存儲過程,java 存儲過程,或外部處處過程需要在觸發(fā)器操作部分直接使用call
? 7) dml 觸發(fā)器觸發(fā)順序
?? (1)dml 觸發(fā)器在單行數(shù)據(jù)上的觸發(fā)順序。
??? 對于單行數(shù)據(jù)而言,無論是語句此觸發(fā)器,還是行觸發(fā)器,觸發(fā)器代碼實際只執(zhí)行一次,并且執(zhí)行
順序為before 語句觸發(fā)器,before 行觸發(fā)器,dml 操作,after 行觸發(fā)器,after 語句觸發(fā)器
?? (2) dml 觸發(fā)器在多行數(shù)據(jù)上的觸發(fā)順序
??? before 語句觸發(fā)器
??? before 行觸發(fā)器
??? after 行觸發(fā)器
??? before行觸發(fā)器
??? after 行觸發(fā)器
??? after語句觸發(fā)器
?? 語句觸發(fā)器只被執(zhí)行一次,而行觸發(fā)器在每個行上都執(zhí)行一次。
? 2) 語句觸發(fā)器
? 當審計dml 操作,或確保dml操作安全執(zhí)行時,可以使用語句觸發(fā)器
? 1 建立before 語句觸發(fā)器
?? create or replace trigger tr_sec_emp
?? before insert or update or delete on emp
?? begin
???? if to_char(sysdate,'DY','nls_dtate_language=AMERICAN') in ('sat','sun') then
???? railse_application_error(-200001,'不能在休息日改變雇員信息');
???? end if;
?? end;?
?? 2 使用條件謂詞
?? inserting ,updating ,deleting
?? create or replace trigger tr_sec_emp
?? before insert or update or delete on emp
?? begin
???? if to_char(sysdate,'DY','nls_date_language=american')
????? in('sat','sun') then
???? case
?????? when inserting then
???????? raise_application('-20001','inserting');
?????? when updating then
???????? raise_application('-20002','updating');
?????? when deleting then
???????? raise_application('-20003','deleting');
???? end case;
??? end if;
?? end;
?? 3 建立after 語句觸發(fā)器
??? 為了dml 操作,或者dml 操作后執(zhí)行匯總運算
?? create table aduit_table(
???? name varchar2(20),ins int,upd int,del int,
???? starttime date,endtime date
?? );
?? create or replace trigger tr_aduit_emp
?? after insert or update or delete emp
?? declare
???? v_temp int;
?? begin
???? select count(*) into v_temp from aduit_table
?????? where name='emp';
???? if v_temp=0 then
?????? insert into audit_table values
?????? ('emp',0,0,0,sysdate,null);
???? end if;
???? case
?????? when? inserting then
???????? update aduit_table set ins=ins+1,endtime=sysdate where name='emp';
?????? when updating then
???????? update audit_table set upd=upd+1,endtime=sysdate where name='emp';
?????? when deleting then
???????? update aduit_table set del=del+1,endtime=sysdate where name='emp';
?? end;
? 3) 行觸發(fā)器
?? 審計數(shù)據(jù)變化可以使用行觸發(fā)器
?? 1 建立不before 行觸發(fā)器
??? 為了取保數(shù)據(jù)符合商業(yè)邏輯或企業(yè)規(guī)則,對輸入的數(shù)據(jù)進行復雜的約束,可以使用before行觸發(fā)器
???? create or replace trigger tr_emp_sal
???? before update of sal on emp
???? for each row
???? begin
?????? if :new.sal<:old.sla then
???????? raisse_application_error(-200010,'工資只漲不降');
?????? end if;
???? end;
???? 2) 建立after 行觸發(fā)器
???? 為了審計dml 操作,可以使用語句觸發(fā)器或oracle 系統(tǒng)提供的審計功能,而為了審計數(shù)據(jù)變化
,則應該使用after 行觸發(fā)器
???? create table audit_emp_change(
?????? name varchar2(10),odl number(6,2),
?????? newsal number(6,2),time date);
??? create or replace trigger tr_sal_change
??? after update of sal on emp
??? for each row
??? declare
???? v_temp int;
??? begin
???? select count(*) into v_temp from audit_emp_change where name=:old.ename;
??? if v_temp =0 then
????? insert into audit_emp_change
??????? values(:old,ename,:old.sal,:new,sal,sysdate);
??? else
????? update audit_emp_change
??????? set oldsal=:old.sal,newsal=:new.sal,time=sysdate where name=:old.ename;?
??? end if;
??? end;
???? )
??? 3) 限制行觸發(fā)器
??? 當使用行觸發(fā)器,默認情況下會咱每個被作用行上七星一次觸發(fā)器代碼,為了時得再特定條件下執(zhí)行行觸發(fā)器代碼,需要使用when 子句
??? create or replace trigger tr_sal_change
??? after update of sal on emp
??? for each row
??? when(old.job='salesman')
??? declare
?????? v_temp int..
2 dml 觸發(fā)器使用注意事項
? 觸發(fā)器代碼不能從觸發(fā)器所對應的基表中讀取數(shù)據(jù)
3 dml 觸發(fā)器
? 為了保證數(shù)據(jù)庫滿足特定的商業(yè)規(guī)則或企業(yè)邏輯,可以使用約束,觸發(fā)器和子程序。約束性能最好,實現(xiàn)最簡單,所以為售選,如果觸發(fā)器不盟實現(xiàn),可以選擇觸發(fā)器。
? dml 觸發(fā)器可以用于實現(xiàn)數(shù)據(jù)安全保護,數(shù)據(jù)審計,數(shù)據(jù)完整性,參照完整性,數(shù)據(jù)復制等功能。
?1) 控制數(shù)據(jù)安全
? create or replace trigger tr_emp_time
? before insert or update or delete on emp
? begin
??? if to_char(sysdate,'hh24') not between '9' and '17' then
????? raise_application_error(-20101,'not work time');
???? end if;
? end;
? 2) 實現(xiàn)數(shù)據(jù)審計
? 使用數(shù)據(jù)審計只能審計sql 操作,而不會記載數(shù)據(jù)變化
? audit insert,update,delete on emp by access
? 3)實現(xiàn)數(shù)據(jù)完整性
? 首選約束 alter table emp add constraint ck_sal check (sal>=800),但是在有些情況下只能使用觸發(fā)器來實現(xiàn)數(shù)據(jù)完整性
?? create or replace trigger tr_check sal
?? before update of sal on emp
?? for each row
?? when (new.sla<old.sal or new.sal>1.2* old.sal)
?? begin
????? raise_application_error(,,,,,,)
?? end;
? 3) 使用引用完整性
? 采用 on delete cascade 可以進行集聯(lián)刪除,但是卻不能進行集聯(lián)更新。采用觸發(fā)器實現(xiàn)集聯(lián)更新
?? create or replace trigger tr_update
?? after update of sal on emp
?? for each row
?? begin
???? update emp set depno=:new.deptno where dentno=:old.deptno;
?? end;
4 建立instead of 觸發(fā)器
? 對于簡單視圖可以直接進行insert update 和delete 等操作,但是對于復雜視圖不允許進行insert,update 和delete 操作。
? 滿足一下條件的為復雜視圖
??? 具有操作集合符 union,union all ,intersect,minus
??? 具有分組函數(shù) min,max,avg,sum,count
??? 具有g(shù)roup by connect 編譯 或start with
??? 具有distinct
??? 具有連接
? 為了在復雜視圖上執(zhí)行dml 操作,必須要基于instead-of 觸發(fā)器,建立instead-of 觸發(fā)器后,就可以基于復雜視圖執(zhí)行insert,update和delete 語句。
?? instead of 選項只使用于視圖
?? 基于視圖建立觸發(fā)器時,不能定義before 和 after
?? 在建立視圖時不能指定 with check option
?? 當建立instead of 觸發(fā)器時,必須指定for each row 選項
? 1) 建立復雜視圖dept_emp
?? create or replace view dept_emp as
?? select a.deptno,a.dname,b,empno,b,ename
?? from dept a,emp b
?? where a,deptno=b.deptno;
? 2) 建立 instead-of 觸發(fā)器
?? create of replacee trigger tr_instead_of_dept_emp
?? instead of insert on dept_emp
?? for each row
?? declare
???? v_temp int;
?? beegin
????? select count(*) into v_temp from dept where deptno=:new.deptno;
????? if v_temp=0 then
??????? insert into dept(deptno,dname) values(:new.deptno,:new.dname);
????? end if;
????? select count(*)into v_temp from emp where empno=:new.empno;
????? if v_temp=0 then
???????? insert into emp(empno,ename,deptno)
?????????? values(:new.deptno,:new.ename,:new.deptno);
???????? end if;
?? end;
??
?? 可以對視圖執(zhí)行insert 操作了
??? insert into dept_emp values(50,'admin','1223','mary')
5 管理觸發(fā)器
? 1) 顯示觸發(fā)器信息
??? select trigger_name,status from user_triggers
??? where table_name='emp';
?? 2)禁止觸發(fā)器
??? alter trigger tr_check_sal disable;
?? 3) 激活觸發(fā)器
??? alter trigger tr_check_sal enable;
?? 4) 禁止或激活表上的所有觸發(fā)器
??? alter table emp disable all triggers;
??? alter table emo eanble all triggers;?
?? 5)重新編譯觸發(fā)器
??? alter trigger tr_check_sal compile;
?? 6) 刪除觸發(fā)器
??? drop trigger tr_check_sal;