如何修复oracle中的变异触发器

时间:2013-02-12 06:33:38

标签: plsql triggers oracle11g

我写了一个触发器来更新同一个表中的列值。对于Ex,我在更新assettype列后在metermaster表上写了一个触发器,在触发器中我试图更新同一metermaster表中的instantaneousinterval列。它抛出这样的错误

错误:ORA-04091:表PSEB.METERMASTER正在变异,触发/功能 可能看不到它。

我的触发器代码如下:

CREATE OR REPLACE TRIGGER PSEB.spiupdate
AFTER
update of assettype
ON pseb.metermaster
referencing new as new old as old
    for each row
DECLARE
vassettype number;
resval number(10);
vassettypename varchar2(50);
vmeterid number;
begin
   select :new.assettype,:new.meterid INTO vassettype,vmeterid from dual;
   select assettypename into vassettypename from pseb.METERASSETINSTTYPE where ASSETTYPEID=vassettype;
    select case when assettypename  like 'DT' then 86400 when assettypename  like 'HT' then 3600 when assettypename  like 'FSB' then 86400 end  into resval from pseb.meterassetinsttype where assettypename =vassettypename; 
    update pseb.metermaster set instantaneousinterval=resval where meterid=vmeterid;
end;

我尝试使用

pragma autonomous_transaction;

但它给出了死锁条件。 错误:ORA-00060:在等待资源时检测到死锁 ORA-06512:

请帮助我解决这个问题。

3 个答案:

答案 0 :(得分:2)

而不是此更新语句

update pseb.metermaster set instantaneousinterval=resval where meterid=vmeterid;

使用

:new.instantaneousinterval=resval;

答案 1 :(得分:1)

当语句导致触发器触发并且该触发器引用导致触发器的表时,会发生变异表。避免此类问题的最佳方法是不使用触发器,但我怀疑DBA没有花时间这样做。他本可以做以下其中一项:

将触发器更改为后触发器。

将其从行级触发器更改为语句级触发器。

转换为复合触发器。

修改触发器的结构以使用行和语句级别触发器的组合。

使触发器自动进行提交。

试试这个pragma autonomous_transaction;提交

答案 2 :(得分:1)

由于触发器正在更新定义它的同一个表,为什么不更新第一个更新语句本身的两列?

,而不是使用像

这样的更新
UPDATE pseb.metermaster
SET    assettype = '<v_assettype>';

并依赖于触发器来更新instantaneousinterval列,为什么不使用如下所示的更新语句(代码未经过测试

UPDATE pseb.metermaster
SET    assettype = '<v_assettype>',
       instantaneousinterval = (SELECT CASE
                                           WHEN assettypename LIKE 'DT' THEN 86400
                                           WHEN assettypename LIKE 'HT' THEN 3600
                                           WHEN assettypename LIKE 'FSB' THEN 86400
                                       END
                               FROM   pseb.meterassetinsttype
                               WHERE  assettypeid = '<v_assettype>');

在我看来,在这种情况下使用触发器和autonomous_transaction是一种错误的方法。要了解这是错误的原因,请在http://asktom.oracle.com/中搜索此错误。