trigger

trigger

 

一、类型:  

  DML触发器:insert、update、delete  

  替代触发器:针对视图  

  系统触发器:针对系统事件

 

二、触发频率:  

  语句级(statement):当触发事件发生时,该触发器只执行一次;  

  行级(row):当触发事件发生时,针对会受到影响的每一行数据,触发器都会执行一次;

 

三、注意:  

  一个表最多只能有12个触发器,且相互不可矛盾、重复;  

  单个触发器最多为32KB;  

  触发器中不能包含事物控制语句(commit,rollback,savepoint);且其中调用的过程和函数语句中也不能有事物控制语言;  

  当触发器中有 “for each row” 选项时,则表示为语句级触发器;         

    缺省 “for each row” 选项时,before 和 after 触发器为语句级触发器,instead of 触发器为行触发器;  

  系统事件:         

    startup           启动数据库实例之后         

    shutdown          关闭数据库实例之前         

    servererror       出现错误之后         

    logon             连接之后         

    logoff            断开连接之前         

    create                    

    drop         

    alter         

    ddl         

    grant         

    revoke         

    rename         

    audit/noaudit                             

 

四、语法:

create or replace trigger 触发器名 出发时间 触发事件       

  on 表名 [for each row]       

  [when condition]       

  [pl/sql]       

 

五、实例: 

5.1、简单 after update

create table test_dept as select * from test_dept;

create or replace trigger test_trigger01 

       after update  

       on test_dept for each row

begin

       dbms_output.put_line(:old.deptno||'=++++++='||:new.deptno);

end;



update test_dept set b='11111' where a='a';

commit;



drop trigger test_trigger01;

drop table test_dept;

 

5.2、deleting,updating,inserting应用,将某表中的数据修改记录插入到另一张表中

 --deleting   只有:old
 --inserting  只有:new
 --updating   :old和:new都有

create table test_dept as select * from dept;

create table test_dept_log as select a.*,'删除' as flag,sysdate as time_ from dept a where 1=2;



create or replace trigger test_trigger02 

       after update or delete or insert  

       on test_dept for each row

begin

       case 

         when updating then 

              insert into test_dept_log values(:old.deptno,:old.dname,:old.loc,'修改',sysdate);

         when inserting then

              insert into test_dept_log values(:new.deptno,:new.dname,:new.loc,'插入',sysdate);

         when deleting then 

              insert into test_dept_log values(:old.deptno,:old.dname,:old.loc,'删除',sysdate);

       end case;

       /*--也可以写成:

         if updating then 

              insert into test_dept_log values(:old.deptno,:old.dname,:old.loc,'修改',sysdate);

         elsif inserting then   --【注意是elsif,而不是elseif】

              insert into test_dept_log values(:new.deptno,:new.dname,:new.loc,'插入',sysdate);

         elsif deleting then 

              insert into test_dept_log values(:old.deptno,:old.dname,:old.loc,'删除',sysdate);

         end if;

       */

end;



update test_dept set loc='test' where deptno=20;       

insert into test_dept values(50,'wer','wer'); 

delete from test_dept where deptno=50;   

select * from test_dept_log;

select * from test_dept;  



drop table test_dept;       

drop table test_dept_log;

drop trigger test_trigger02;

5.3、当前用户不是scott,则不允许修改

create table test_dept as select * from dept;

create or replace trigger test_trigger03 

       before update or insert or delete 

       on test_dept

       for each row

--when ((select count(*) from dual where user)='SCOTT'>0)

when (upper(user)<>'SCOTT')

declare tt varchar2(20);

begin

  select user into tt from dual;

  raise_application_error(-20001,'当前用户是'||tt||',没有操作权限!');

end;



update test_dept set loc='test_' where deptno=20;

select * from test_dept;



drop table test_dept;

drop trigger test_trigger03;

5.4、instead of触发器,建立在视图上,且该视图没有指定 with check option 选项;

create table test01(

       a number(10),

       b number(10),

       c number(10));

create table test02 as 

       select * from test01 where 1=2;

create view test_view01 as 

       select a.a,b.b from test01 a,test02 b where a.a=b.a and a.b=b.b;



create or replace trigger test_trigger04 

       instead of insert

       on test_view01

       for each row

begin

       --raise_application_error(-20001,'视图不可插入数据!');

       insert into test01 values (:new.a,null,null);

       insert into test02 values (null,:new.b,null);

end;



insert into test_view01 values(1,1);

insert into test_view01 

       select 2,2 from dual

       union all

       select 3,3 from dual;

select * from test01;

select * from test02;



drop view test_view01;

drop trigger test_trigger04;

drop table test02;

drop table test01;

5.5、将用户登陆和登出记录到数据表
--创建系统触发器,用户需要有administer database trigger权限
--以下操作在sys用户下可成功完成

create table test_login(

       event_ varchar2(10),

       user_ varchar2(20),

       address_ varchar2(100),

       date_ date

       );

create or replace trigger test_trigger05 

       after logon on database

begin

       insert into test_login values('登陆',user,ora_client_ip_address,sysdate);

end;        



create or replace trigger test_trigger06 

       before logoff on database

begin

       insert into test_login values('登出',user,ora_client_ip_address,sysdate);

end; 



drop table test_login;

drop trigger test_trigger05;

drop trigger test_trigger06;

 

你可能感兴趣的:(trigger)