【问题标题】:How to fix the mutating trigger in oracle如何修复oracle中的变异触发器
【发布时间】:2013-02-12 15:15:50
【问题描述】:

我编写了用于更新同一个表中的列值的触发器。对于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:

请帮我解决这个问题。

【问题讨论】:

    标签: plsql triggers oracle11g


    【解决方案1】:

    代替这个更新语句

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

    使用

    :new.instantaneousinterval=resval;
    

    【讨论】:

      【解决方案2】:

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

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

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

      转换为复合触发器。

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

      通过提交使触发器自治。

      试试这个编译指示autonomous_transaction;与提交

      【讨论】:

        【解决方案3】:

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

        即,而不是使用类似的更新

        UPDATE pseb.metermaster
        SET    assettype = '<v_assettype>';
        

        并且依靠触发器来更新瞬时间隔列,为什么不使用如下更新语句(代码未测试

        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>');
        

        在我看来,在这种情况下使用触发器和自治事务将是错误的方法。要知道为什么会出现此错误,请搜索 http://asktom.oracle.com/ 以查找此错误。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-05-21
          • 1970-01-01
          • 2011-01-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多