0

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

请帮我解决这个问题。

4

3 回答 3

2

而不是这个更新语句

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

采用

:new.instantaneousinterval=resval;
于 2013-02-12T06:41:15.187 回答
1

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

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

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

转换为复合触发器。

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

通过提交使触发器具有自主性。

试试这个编译指示自治事务;与提交

于 2013-02-12T06:40:27.280 回答
1

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

即,而不是使用更新

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/中搜索此错误。

于 2013-02-12T07:15:50.307 回答