之变通处理:我们不妨做一下变通处理.将行级级触发器变通成语句级触发器.看下面的处理.

 

     1.
创建一个package:emp_pkg .
CREATE OR REPLACE PACKAGE emp_pkg AS
    /* ----------------------------------
       --Author:Kevin.yuan
       --create_time: 2008 -07-01
    ---------------------------------- */
     TYPE crArray IS TABLE OF emp%ROWTYPE INDEX BY BINARY_INTEGER;
     oldRows crArray; --accept the old values of emp
     oldEmpty crArray;  --initialize values
     END emp_pkg;

 

     2.
创建一个语句级trigger,用来触发trigger的时候清空初始化数据.
CREATE OR REPLACE TRIGGER emp_bd_st BEFORE DELETE ON emp
    /*----------------------------------
      Author:Kevin.yuan
      create_time: 2008 -07-01
    ---------------------------------- */
     BEGIN
       emp_pkg.oldRows := emp_pkg.oldEmpty;
     END emp_bd_st;

 

     3.
创建一个行级trigger:emp_d,问题的核心和关键就在这里,这个trigger
 
并不参与业务逻辑,只是将触发到的数据载入到emp_pkg.oldRows记录表里面去.
CREATE OR REPLACE TRIGGER emp_d AFTER DELETE ON emp FOR EACH ROW
    /* ----------------------------------
       --Author:Kevin.yuan
       --create_time: 2008 -07-01
    ---------------------------------- */
    DECLARE
    --ct is the position of the deleted records
    ct INTEGER := emp_pkg.oldRows.COUNT + 1;
    BEGIN
     emp_pkg.oldRows(ct).ename := :OLD.ename;
     emp_pkg.oldRows(ct).deptno := :OLD.deptno;
    END emp_d;

 

     4.
创建一个语句级trigger:emp_d_st,前面3步都是为这一步服务的,这一步
 
真正参与业务逻辑处理.
CREATE OR REPLACE TRIGGER emp_d_st AFTER DELETE ON emp
    /* ----------------------------------
       --Author:Kevin.yuan
       --create_time: 2008 -07-01
     ---------------------------------- */
    DECLARE
    BEGIN
    FOR i IN 1 .. emp_pkg.oldRows.COUNT LOOP
    INSERT INTO emp_log
      (ename, dname, dates)
      select emp_pkg.oldRows(i) .ename, dname, sysdate
        from dept
       WHERE deptno = emp_pkg.oldRows(i).deptno;
    END LOOP;
    END emp_d_st;

 

    
来看一下变通后的触发器是否满足我们的业务要求:

 

 SQL> alter trigger emp_del_trg disable;

 

 Trigger altered

 

    
删除emp数据

 

 SQL> delete from emp where rownum<3;

 

 2 rows deleted

 

 SQL> select * from emp_log;

 

 ENAME DNAME DATES
 
——————–
 
——————–
 
———–
 SMITH RESEARCH 2008-7-1 19
 ALLEN SALES 2008-7-1 19

 

 SQL> rollback;

 

 Rollback complete

 

    
删除dept数据.

 

 SQL> delete from dept;

 

 4 rows deleted

 

 SQL> select * from emp_log;

 

 ENAME DNAME DATES
 
——————–
 
——————–
 
———–

 

   
至此,目的实现.由于用了多于常规数量的触发器,对系统性能会造成一定影响,而且,无疑会加重系统后期业务维护负担,因此,良好的数据库逻辑设计和代码编写思路是很必要的,否则,只能走另外一些路径,不过,这个由行级触发器变语句级别触发器的思路,还是有必要的,当trigger中无法避免的需要access自身表的时候,这无疑是个可以借鉴的解决方案。