ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 触发器总结

触发器总结

原创 Linux操作系统 作者:chwang1984 时间:2010-04-26 14:54:10 0 删除 编辑
定义:触发器是一种特殊的存储过程,它在插入,删除或修改特定表中的数据时触发执行,它比数据库本身标准的功能有更精细和更复杂的数据控制能力。(特定事件出现的时候,自动执行的代码块。)
功能:
1、 允许/限制对表的修改
2、 自动生成派生列,比如自增字段
3、 强制数据一致性
4、 提供审计和日志记录
5、 防止无效的事务处理
6、 启用复杂的业务逻辑

ORACLE产生数据库触发器的语法为:
create [or replace] trigger 触发器名 触发时间 触发事件
on 表名
[for each row]
pl/sql 语句
其中:
触发器名:触发器对象的 名称。由于触发器是数据库自动执行的,因此该名称只是一个名称,没有实质的用途。
触发时间:指明触发器何时执行,该值可取:
     before--- 表示在数据库动作之前触发器执行;
     after---表示在数据库动作之后出发器执行。
触发事件:指明哪些数据库动作会触 发此触发器:
     insert:数据库插入会触发此触发器;
     update:数据库修改会触发此触发器;
     delete: 数据库删除会触发此触发器。
表 名:数据库触发器所在的表。
for each row:对表的每一行触发器执行一次。如果没有这一选项,则只对整个表执行一次。
举例:下面的触发器在更新表auths之前触发,目的是 不允许在周末修改表:
create trigger auth_secure
   before insert or update or delete         //对整表更新前触发
   on auths
begin
   if(to_char(sysdate,'DY')='SUN'
           RAISE_APPLICATION_ERROR(-20600,' 不能在周末修改表auths');
   end if;
end

触发器可以包括任何合法的PL/sQL语句,假有以下例外
1.触发器不可以执行COMMIT、ROLLBACK或 SAVEPOINT语句,而且不可以调用执行这些语句之一的函数或过程。
2.触发器不可以声明long或LONG RAW变量。
3.触发 器不可以在定义它的表上执行DML操作。


CREATE OR REPLACE TRIGGER TRI_KCYXZ1_SFJCHZ
  BEFORE  update or insert on KCYXZ1
  for each row

declare PJLX varchar2(1);
begin
PJLX:=:NEW.KCYXZ1_PJLX;
IF (PJLX='M') THEN
:NEW.KCYXZ1_SFJCHZ:='0';

END IF;

end;
来替换操作表的update

异常解决:

解决ORA- 04091:表XX发生编码,触发器/函数不能读它

解决:通过declare  PRAGMA AUTONOMOUS_TRANSACTION,保证每行插入动作为自治事务,必须加上commit



Example:
create or replace trigger tr_road_name_no_i_u
  after insert or update on road 
  for each row
declare
  PRAGMA AUTONOMOUS_TRANSACTION;
  v_count number;
begin
  select count(1)
    into v_count
    from road t
   where t.name <> :new.name
     and t.no = :new.no
     and (t.xh > :new.XH or t.xh < :new.XH);

  if v_count > 0 then
    raise_application_error(-20056, 'aaaaaaaaaaaa');
  end if;
  select count(1)
    into v_count
    from road t
   where t.name = :new.name
     and t.no <> :new.no
     and (t.xh > :new.XH or t.xh < :new.XH);
  if v_count > 0 then
    raise_application_error(-20056, 'bbbbbbbbbbbb');
  end if;
  commit;
end tr_i_u_road;



下边是在网上搜索的,蛮好的设计想法,通过自己测试,可以通过,贴出来,作为参考:
使用临时表  
   
  11:04:36   SQL>   CREATE   GLOBAL   TEMPORARY   TABLE   Tmp(  
  11:04:39       2     rid   varchar2(20))ON   COMMIT   DELETE   ROWS;  
   
  表已创建。  
   
  已用时间:     00:   00:   00.16  
  11:07:30   SQL>   create   or   replace   trigger   trg_tb    
  11:07:36       2     after   insert   on   tb  
  11:07:36       3     for   each   row  
  11:07:36       4     begin  
  11:07:36       5     if   :new.col2='laji'   then  
  11:07:36       6       insert   into   tmp   values(:new.rowid);  
  11:07:36       7     end   if;  
  11:07:36       8     end   trg_tb;  
  11:07:36       9     /  
   
  触发器已创建  
   
  已用时间:     00:   00:   00.47  
  11:07:36   SQL>   create   or   replace   trigger   trg_tb_del  
  11:07:44       2     after   insert   on   tb  
  11:07:46       3     begin  
  11:07:46       4     delete   from   tb   where   exists(select   1   from   tmp   where   rid=tb.rowid);  
  11:07:46       5     end   trg_tb_del;  
  11:07:46       6     /  
   
  触发器已创建  
   
  已用时间:     00:   00:   00.31  
  11:08:59   SQL>   select   count(1)   from   tb;  
   
      COUNT(1)  
  ----------  
                  22  
   
  已用时间:     00:   00:   00.00  
  11:09:08   SQL>   insert   into   tb(col1,col2)   values('aaa','laji');  
   
  已创建   1   行。  
   
  已用时间:     00:   00:   00.00  
  11:09:12   SQL>   select   count(1)   from   tb;  
   
      COUNT(1)  
  ----------  
                  22  
   
  已用时间:     00:   00:   00.16  
  11:09:14   SQL>    
   
  说明刚才插入的数据已经被删除掉了。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/17179887/viewspace-660796/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2009-03-27

  • 博文量
    96
  • 访问量
    185871