我有两个表,名称分别为item
和stock_item
。
当我更新item
表时,将触发名称为beforeItem
的触发器,这将从qty
中减去新的更新后的stock_qty
。但是它会抛出
ORA-04091:表****正在突变触发器/功能可能看不到
我该如何解决?
我的桌子:
create table stock_item
(no number primary key,itemName varchar2(10),stock_Qty number);
create table item
(no number,Name varchar2(10),qty number);
我的触发器
create or replace trigger beforeItem
before update on item
for each row
declare
chk_no number;
chk_item varchar2(10);
chk_qty number;
--pragma AUTONOMOUS_TRANSACTION;
-- this code will skip the update code.
begin
select no,name,qty into chk_no, chk_item,chk_qty from item where no=:new.no
and name=:new.name;
update stock_item set itemName = itemName - chk_qty where no=chk_no and
itemName=chk_item;
--commit;
end;
答案 0 :(得分:0)
当触发器针对拥有该触发器的表发出DML时,Oracle催促ORA-04091;这包括SELECT语句。原因很简单:表的状态未知,因为触发器在事务期间触发 ,因此触发器DML的结果是不可预测的。
解决方案通常很简单:删除DML。这肯定是这里的答案,因为您的:NEW记录具有在stock_item
上执行更新所需的所有值:
create or replace trigger beforeItem
before update on item
for each row
begin
update stock_item si
set si.stock_Qty = si.stock_Qty - :new.qty
where si.no = :new.no;
end;
但是stock_item表不知道要减去的项目表qty的当前值是多少。
好的,也就是说,您想使用旧(当前)ITEM.QTY与新(更新)值之间的差异来更新STOCK_ITEM.QTY。那样的话:
create or replace trigger beforeItem
before update on item
for each row
begin
update stock_item si
set si.stock_Qty = si.stock_Qty - (nvl(:old.qty,0) - nvl(:new.qty,0))
where si.no = :new.no;
end;
这是我在SQL Fiddle上的解决方案的演示。
顺便说一句,请注意,我已更正了您的UPDATE语句:从库存名称中减去项目数量确实没有任何意义。另外,在需要使用主键的WHERE子句中也无需使用itemName
。
答案 1 :(得分:0)
您不能在此触发器中引用表ITEM,因为它会导致您的错误。代替使用SELECT语句,而是使用新/旧参数。尝试使用此版本的触发器。
create or replace trigger beforeItem
before update on item
for each row
begin
-- if :new.qty is not null then
update stock_item set
-- logic to maintaint if no changes on qty field were done
stock_Qty = stock_Qty - ( nvl(:new.qty,0) - nvl(:old.qty,0) )
where no=:new.no and itemName=:new.name;
-- end if;
end;