2

我有一个在表中插入新记录时触发的触发器,因为我想在同一个表中插入新记录。
我的触发器是:

create or replace trigger inst_table
after insert on test_table referencing new as new old as old  
for each row
declare 
      df_name varchar2(500);
      df_desc varchar2(2000);

begin
      df_name := :new.name;
      df_desc := :new.description;

     if inserting then
          FOR item IN (SELECT pid FROM tbl2 where pid not in(1))
             LOOP
                 insert into test_table (name,description,pid) values(df_name,df_desc,item.pid); 
             END LOOP;    
     end if; 
end;

它给出一个错误,比如

ORA-04091: table TEST_TABLE is mutating, trigger/function may not see it

我认为它阻止我插入同一张桌子。
那么如何将这条新记录插入到同一张表中。

注意:- 我使用Oracle 作为数据库

4

3 回答 3

10

每当您有一个修改您正在触发的表的行级触发器时,都会发生突变。问题是甲骨文不知道如何表现。您插入一行,触发器本身将一行插入到同一个表中,Oracle 感到困惑,原因,那些由于触发器而插入到表中的,它们是否也受到触发器操作的影响?

解决方案是一个三步过程。

1.) 触发器之前的语句级别实例化一个包,该包将跟踪插入的行。

2.) 将行信息保存到在上一步中实例化的包变量中的触发器之前或之后的行级。

3.) 插入表的触发器后的语句级,所有保存在包变量中的行。

这方面的一个例子可以在这里找到:

http://asktom.oracle.com/pls/asktom/ASKTOM.download_file?p_file=6551198119097816936

希望有帮助。

于 2011-11-17T13:00:41.130 回答
1

我会说你应该看看除了触发器之外的任何方式来实现这一点。正如 Mark Bobak 的回答中提到的,触发器正在插入一行,然后对于触发器插入的每一行,然后需要调用触发器来插入更多行。

我会考虑编写一个存储过程来创建插入,或者只是通过子查询而不是通过值插入。

触发器可以用来解决简单的问题,但是当解决更复杂的问题时,它们只会让人头疼。

值得阅读APC 发布的这个重复问题的答案以及 Tom Kyte 的这篇文章。顺便说一句,该文章也在重复问题中被引用,但链接现在已过时。

于 2011-11-17T13:32:07.767 回答
1

尽管在抱怨触发器有多糟糕之后,这是另一个解决方案。

也许你需要看看有两张桌子。像现在一样将数据插入test_table表中。但不是让触发器在表中插入额外的行,而是test_table有一个包含数据的明细表。然后触发器可以将所有需要的行插入到明细表中。

如果您在两个表之间有删除级联外键关系,您可能会再次遇到变异触发器错误,因此最好避免这种情况。

于 2011-11-17T13:43:12.077 回答