执行Oracle存储过程触发ORA-04091表变异错误问题咨询
故障根因
你遇到的ORA-04091是Oracle的变异表错误,触发规则是:行级触发器(声明了FOR EACH ROW)运行期间,不允许直接读取/修改触发该触发器的表本身。
你当前的触发器是payment表的UPDATE行级触发器,内部又写了SELECT语句查询payment表,哪怕把触发时机从AFTER改成BEFORE,也依然违反这个限制,因此问题没有解决。
另外你写的SELECT查询完全没有必要:行级触发器内置的:old伪记录可以直接获取当前被更新行的所有字段更新前的原值,不需要额外查表。
修复方案
直接修改触发器,删除所有冗余的查表逻辑,直接用:old取值即可,修改后的触发器代码如下:
CREATE OR REPLACE trigger trg_payment_validation before update on payment for each row BEGIN -- 直接用:old取当前行更新前的状态,不需要查表 if :old.paymentstatus = 'Paid' then RAISE_APPLICATION_ERROR( -20950, 'You already paid for your trip, have a nice day' ); -- 注意:你当前存储过程的UPDATE语句没有更新paymentamount字段,该判断暂时无效 elsif :new.paymentamount < :old.paymentamount then RAISE_APPLICATION_ERROR( -20950, 'Insufficient amount entered, pls pay the exact amount' ); end if; END; /
额外逻辑修正提示
你的存储过程当前存在逻辑遗漏:UPDATE语句没有将传入的AMT_PAY参数写入paymentamount字段,导致支付金额校验逻辑完全无效。如果需要实现金额校验,需要将存储过程的UPDATE语句修改为:
UPDATE Payment SET paymenttype = PAYMENT_TYPE, paymentdate = TO_CHAR(sysdate,'DD/MON/YYYY'), paymentstatus = v_paymentstatus, paymentamount = AMT_PAY -- 新增该行,把传入的支付金额写入表 where paymentid = PAYMENT_ID;
内容的提问来源于stack exchange,提问作者Joshua Tabi
相关产品推荐
相关产品推荐

