oracle触发器 删除出发,插入或删除后的Oracle触发器

您遇到的是经典的“变异表”异常。在ROW触发器中,Oracle不允许您对定义触发器的表运行查询 - 因此它是导致此问题的触发器部分中的SELECTTABLE1 DELETING。

有几种方法可以解决这个问题。在这种情况下,最好的方法是使用复合触发器,它看起来像:

CREATE OR REPLACE TRIGGER TABLE1_NUM_TRG

FOR INSERT OR DELETE ON TABLE1

COMPOUND TRIGGER

TYPE NUMBER_TABLE IS TABLE OF NUMBER;

tblTABLE2_IDS  NUMBER_TABLE;

BEFORE STATEMENT IS

BEGIN

tblTABLE2_IDS := NUMBER_TABLE();

END BEFORE STATEMENT;

AFTER EACH ROW IS

BEGIN

IF INSERTING THEN

UPDATE TABLE2 t2

SET    t2.TABLE2NUM = :new.NUM

WHERE  t2.ID = :new.TABLE2_ID;

ELSIF DELETING THEN

tblTABLE2_IDS.EXTEND;

tblTABLE2_IDS(tblTABLE2_IDS.LAST) := :new.TABLE2_ID;

END IF;

END AFTER EACH ROW;

AFTER STATEMENT IS

BEGIN

IF tblTABLE2_IDS.COUNT > 0 THEN

FOR i IN tblTABLE2_IDS.FIRST..tblTABLE2_IDS.LAST LOOP

UPDATE TABLE2 t2

SET t2.TABLE2NUM = (SELECT NUM

FROM (SELECT t1.NUM

FROM TABLE1 t1

WHERE t1.TABLE2_ID = tblTABLE2_IDS(i)

ORDER BY modification_date DESC)

WHERE ROWNUM = 1)

WHERE t2.ID = tblTABLE2_IDS(i);

END LOOP;

END IF;

END AFTER STATEMENT;

END TABLE1_NUM_TRG;

的化合物,触发允许每个定时点(BEFORE STATEMENT,BEFORE ROW,AFTER ROW,和AFTER STATEMENT),以进行处理。请注意,始终按给定的顺序调用时间点。当执行适当的SQL语句(即INSERT INTO TABLE1或DELETE FROM TABLE1)并触发此触发器时,将调用的第一个时间点BEFORE STATEMENT,以及BEFORE STATEMENThandler将分配一个PL / SQL表来保存一堆数字。在这种情况下,要存储在PL / SQL表中的数字将是TABLE1中的TABLE2_ID值。(例如,使用PL / SQL表而不是数组,因为表可以容纳不同数量的值,而如果我们使用数组,我们必须事先知道需要存储多少个数。我们事先不能知道特定语句会影响多少行,因此我们使用PL / SQL表)。当AFTER EACH ROW达到时间点并且我们发现正在处理的语句是INSERT时,触发器就会继续执行并对TABLE2执行必要的UPDATE,因为这不会导致问题。但是,如果正在执行DELETE,则触发器将TABLE1.TABLE2_ID保存到先前分配的PL / SQL表中。当。。。的时候AFTER STATEMENT 最终达到定时点,迭代先前分配的PL / SQL表,并且对于找到的每个TABLE2_ID执行适当的更新。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值