使用触发器

1 触发器简介
  1) 触发事件
  2) 触发条件
  3) 触发操作
     . 触发器代码的大小不能超过32k,如果使用大量代码建立触发器,应该先建立存储过程,然后再触发器中使用call语句调用存储过程。
     . 触发器中正能含有select ,insert,update 和delete 语句,而不能含有ddl 语句,和事物控制语句。
2 建立dml 触发器
 1) 触发时机
  before,after 表示在执行dml操作之后触发器
 2)触发事件
  insert ,update 和delete 操作。也可以使用书法事件
 3) dml 触发器是针对特定表进行的 因此必须制定dml 操作所对应的表
 4) 触发器类型 用于指定当触发器事件之后,需要执行几次触发器操作。如果指定语句触发器类型
那么会执行一次触发器代码:如果指定行触发器类型,则会在每个被作用行上执行一次触发器代码。
 5) 触发条件
 用于指定执行行触发器代码的条件,只有为ture时,才会执行行触发器代码。
  6) 如果使用pl/sql 存储过程,java 存储过程,或外部处处过程需要在触发器操作部分直接使用call
  7) dml 触发器触发顺序
   (1)dml 触发器在单行数据上的触发顺序。
    对于单行数据而言,无论是语句此触发器,还是行触发器,触发器代码实际只执行一次,并且执行
顺序为before 语句触发器,before 行触发器,dml 操作,after 行触发器,after 语句触发器
   (2) dml 触发器在多行数据上的触发顺序
    before 语句触发器
    before 行触发器
    after 行触发器
    before行触发器
    after 行触发器
    after语句触发器
   语句触发器只被执行一次,而行触发器在每个行上都执行一次。
  2) 语句触发器
  当审计dml 操作,或确保dml操作安全执行时,可以使用语句触发器
  1 建立before 语句触发器
   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 语句触发器
    为了dml 操作,或者dml 操作后执行汇总运算
   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) 行触发器
   审计数据变化可以使用行触发器
   1 建立不before 行触发器
    为了取保数据符合商业逻辑或企业规则,对输入的数据进行复杂的约束,可以使用before行触发器
     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 行触发器
     为了审计dml 操作,可以使用语句触发器或oracle 系统提供的审计功能,而为了审计数据变化
,则应该使用after 行触发器
     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) 限制行触发器
    当使用行触发器,默认情况下会咱每个被作用行上七星一次触发器代码,为了时得再特定条件下执行行触发器代码,需要使用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 触发器使用注意事项
  触发器代码不能从触发器所对应的基表中读取数据
3 dml 触发器
  为了保证数据库满足特定的商业规则或企业逻辑,可以使用约束,触发器和子程序。约束性能最好,实现最简单,所以为售选,如果触发器不盟实现,可以选择触发器。
  dml 触发器可以用于实现数据安全保护,数据审计,数据完整性,参照完整性,数据复制等功能。
 1) 控制数据安全
  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) 实现数据审计
  使用数据审计只能审计sql 操作,而不会记载数据变化
  audit insert,update,delete on emp by access
  3)实现数据完整性
  首选约束 alter table emp add constraint ck_sal check (sal>=800),但是在有些情况下只能使用触发器来实现数据完整性
   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 可以进行集联删除,但是却不能进行集联更新。采用触发器实现集联更新
   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 触发器
  对于简单视图可以直接进行insert update 和delete 等操作,但是对于复杂视图不允许进行insert,update 和delete 操作。
  满足一下条件的为复杂视图
    具有操作集合符 union,union all ,intersect,minus
    具有分组函数 min,max,avg,sum,count
    具有group by connect 编译 或start with
    具有distinct
    具有连接
  为了在复杂视图上执行dml 操作,必须要基于instead-of 触发器,建立instead-of 触发器后,就可以基于复杂视图执行insert,update和delete 语句。
   instead of 选项只使用于视图
   基于视图建立触发器时,不能定义before 和 after
   在建立视图时不能指定 with check option
   当建立instead of 触发器时,必须指定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 触发器
   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;
  
   可以对视图执行insert 操作了
    insert into dept_emp values(50,'admin','1223','mary')
5 管理触发器
  1) 显示触发器信息
    select trigger_name,status from user_triggers
    where table_name='emp';
   2)禁止触发器
    alter trigger tr_check_sal disable;
   3) 激活触发器
    alter trigger tr_check_sal enable;
   4) 禁止或激活表上的所有触发器
    alter table emp disable all triggers;
    alter table emo eanble all triggers; 
   5)重新编译触发器
    alter trigger tr_check_sal compile;
   6) 删除触发器
    drop trigger tr_check_sal;

posted on 2006-10-11 14:44 康文 阅读(1013) 评论(0)  编辑  收藏 所属分类: 数据库


只有注册用户登录后才能发表评论。


网站导航:
博客园   IT新闻   Chat2DB   C++博客   博问  
 
<2006年10月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

导航

统计

常用链接

留言簿(1)

随笔分类

随笔档案

文章档案

搜索

最新评论

阅读排行榜

评论排行榜