日期:2014-05-16  浏览次数:20475 次

ORA-04091 关于在oracle行级触发器中访问本表的错误解决
今天写了个触发器,创建的是行级触发器,
对于oracle行级触发器(for each row),不能对本表做任何操作,包括读取
原则:
在before insert触发器中,可以实现对本表的访问;
在after insert触发器中,不能实现对本表的访问;
在before/after update/delete触发器中,都不能实现对本表的访问

如果插入或修改一条数据时,需要更新另一张表的数据,但是由于在触发器中需要访问触发器本表,一直报ORA-04091错误,如果不使用行级触发器,那么则不能根据 ld.field1 , :NEW.field1访问新旧数据,在网络搜索百般后终于找到实用的解决方法,通过自治事务实现(修改触发器)。
现在将大致的测试场景重现。

原因:在行级触发器中,不能查询自身表
场景重现:通过触发器实现test_count表中统计test表中行数
--创建子表
create table TEST
(id NUMBER, name varchar2(100), primary key (id));
--创建统计表
create table test_count (test_count int);
--创建触发器
CREATE OR REPLACE TRIGGER T_TEST
  AFTER INSERT OR DELETE ON TEST
  FOR EACH ROW
DECLARE
  A NUMBER;
BEGIN
  SELECT  COUNT(*) INTO A FROM TEST;
  UPDATE TEST_COUNT SET TEST_COUNT = A;
END T_TEST;

模拟错误:
INSERT INTO TEST (ID,NAME)VALUES(2,'abc');
ORA-04091: table CHF.TEST is mutating, trigger/function may not see it
ORA-06512: at "CHF.T_TEST", line 2
ORA-04088: error during execution of trigger 'CHF.T_TEST'

处理方法:
通过自治事务实现(修改触发器)
CREATE OR REPLACE TRIGGER T_TEST
  AFTER INSERT OR DELETE ON TEST
  FOR EACH ROW
DECLARE
  A NUMBER;
  PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
  SELECT  COUNT(*) INTO A FROM TEST;
  UPDATE TEST_COUNT SET TEST_COUNT = A;
  COMMIT;
END T_TEST;

PRAGMA AUTONOMOUS_TRANSACTION
当前的触发器作为已有事务的子事务运行,子事务自治管理,子事务的commit、rollback操作不影响父事务的状态

解决方法来自 http://www.xifenfei.com/1214.html/comment-page-1 懒得编辑后面照搬过来了,纯属资料学习,别无它用,谢谢。