我写了一个触发器来更新同一个表中的列值。对于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:
请帮助我解决这个问题。
答案 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/中搜索此错误。