更新触发器以更新到同一个表中

时间:2013-01-06 13:52:07

标签: database oracle plsql triggers ora-04091

create or replace trigger admin.patreg_paid_amt_temp
before UPDATE OF PAIDAMOUNT_TEMP ON admin.patient_registration
REFERENCING OLD AS OLD NEW AS NEW
For EACH ROW 
BEGIN
   if :new.PAIDAMOUNT_TEMP != :old.PAIDAMOUNT_TEMP
   then
       UPDATE admin.patient_registration d
        set d.PAID_AMOUNT = :new.PAIDAMOUNT_TEMP + d.DIFFERENCE ,
        d.PENDING = ABS(:new.PAIDAMOUNT_TEMP - d.DUES) 
       where d.PATIENT_ID = :new.PATIENT_ID;
   end if;
END;

我知道这是因为触发器无法更改其读取的表的内容 任何人都可以帮助我完成这个

当我在发生错误后编写此查询时

update admin.patient_registration set paidamount_temp= 1000 where patient_id=11;

执行请求的操作时遇到错误

ORA-04091 :表格Admin.PATIENT_REGISTRATION正在变异,触发/功能可能看不到它 ORA-06512 :位于“ADMIN.PATREG_PAID_AMT_TEMP”,第4行 ORA-04088 :执行触发器“ADMIN.PATREG_PAID_AMT_TEMP”期间出错 04091. 000000-“表%s。%s正在变异,触发/功能可能看不到它”

2 个答案:

答案 0 :(得分:3)

我们可以在触发器中操纵:NEW值:

if :new.PAIDAMOUNT_TEMP != :old.PAIDAMOUNT_TEMP
then
    :new.PAID_AMOUNT := :new.PAIDAMOUNT_TEMP + :old.DIFFERENCE;
    :new.PENDING := ABS(:new.PAIDAMOUNT_TEMP - :new.DUES);
    :new.difference := :new.total_charges - :new.per_day_charges;
end if;

现在我们知道每个患者有一个PATIENT_REGISTRATION记录(即PATIENT_ID是主键)我们也知道我的解决方案将起作用,你不会得到变异表错误。

答案 1 :(得分:0)

首先,我想说明你不应该以这种方式设计你的逻辑。我不知道上面你的触发器是什么,但应该是 upper 层的角色来更新PAID_AMOUNTPENDING值。将应用程序逻辑置于触发器中只会导致混乱。

但是。如果您无法控制数据库上方的应用程序并且必须执行此操作,那么您应该将触发器更改为for each statement。在其中创建一个循环来迭代NEW_TABLE并相应地更新每一行。但请记住在您的更新中添加一个条件:

UPDATE admin.patient_registration d
    set d.PAID_AMOUNT = p_PAIDAMOUNT_TEMP + p_DIFFERENCE 
    where d.PAID_AMOUNT != (p_PAIDAMOUNT_TEMP + p_DIFFERENCE) -- this is important
    and d.patient_id != p_patient_id

防止触发器触发自身。

在'statement'触发器中,你可以修改trigger的'base'表。

Here你可以阅读更多相关信息。

相关问题