错误"ORA-04091: table is mutating, trigger/function may not see it"的原因以及解决办法

错误的原因
该错误是在编写trigger时常遇到的问题,其根本原因是由于对本表的操作造成的。对于使用了for each row 的触发器,做了DML操作(delete,update,insert),还没有提交时,是不允许其他PL/SQL对本表的DML操作,以及查询,因为此时数据不一致。

解决办法:

1 自治事务

自治事物的概念:就是在subprogram里进行事物的提交不影响主程序的事务,同样主程序的提交或回滚都不影响子程序的commit,即子程序的事物和主程序的事物完全独立。
示例:

[java] view plain copy
 
  1. CREATE OR REPLACE TRIGGER TR_T  
  2.   AFTER DELETE ON T  
  3.   FOR EACH ROW  
  4.   DECLARE V_COUNT NUMBER;  
  5.   PRAGMA AUTONOMOUS_TRANSACTION;  
  6.   BEGIN  
  7.      INSERT INTO T VALUES(:OLD.ID,:OLD.MC,SYSDATE);  
  8. END TR_DEL_CABLE;  

 

PRAGMA AUTONOMOUS_TRANSACTION:就是对自治事务的声明

要注意的就是:自治事务必须慎用,因为一个DML可能会产生许多个独立的事物,这很容易引发死锁,ASKTOM上对AUTONOMOUS_TRANSACTION的看法是:唯一的用途就是作审计日志,其他一概不该使用。

2 网上还有人给出了另一种解决办法:建临时表

新建了与要操作的表结构完全相同的临时表,使得在本表上的触发器读写建好的临时表,再用临时表上的触发器写回本表,也倒是个办法,但是不是最好的,过于繁琐

治本之法Oracle的绝大多数类型的trigger都不支持dml原表,最好是把此逻辑放到触发器外面,另写存储过程实现原有功能

posted @ 2016-12-13 18:33  左正  阅读(4915)  评论(0编辑  收藏  举报