插入或删除后的Oracle触发器
对不起我的英语不好. 我有2张桌子: Table1 id table2_id num modification_date 和 Table2 id table2num 我想创建一个触发器,在Table1中插入或删除后更新Table2.table1lastnum中的最后一个值num. 我的触发器: CREATE OR REPLACE TRIGGER TABLE1_NUM_TRG AFTER INSERT OR DELETE ON table1 FOR EACH ROW BEGIN IF INSERTING then UPDATE table2 SET table2num = :new.num WHERE table2.id = :new.table2_id; ELSE UPDATE table2 SET table2num = (SELECT num FROM (SELECT num FROM table1 WHERE table2_id = :old.table2_id ORDER BY modification_date DESC) WHERE ROWNUM <= 1) WHERE table2.id = :old.table2_id; END IF; END TABLE1_NUM_TRG; 但在Table1删除后我有错误: ORA-04091: table BD.TABLE1 is mutating,trigger/function may not see it ORA-06512: at "BD.TABLE1_NUM_TRG",line 11 ORA-04088: error during execution of trigger 'BD.TABLE1_NUM_TRG' 我究竟做错了什么? 解决方法您遇到的是经典的“变异表”异常.在ROW触发器中,Oracle不允许您对定义触发器的表运行查询 – 因此它是导致此问题的触发器的DELETING部分中针对TABLE1的SELECT.有几种方法可以解决这个问题.在这种情况下,最好的方法是使用复合触发器,它看起来像: 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; 复合触发器允许处理每个定时点(前声明,前行,后行和后声明).请注意,始终按给定的顺序调用时间点.当执行适当的SQL语句(即INSERT INTO TABLE1或DELETE FROM TABLE1)并触发此触发器时,要调用的第一个时间点将是BEFORE STATEMENT,并且BEFORE STATEMENT处理程序中的代码将分配PL / SQL表拿着一堆数字.在这种情况下,要存储在PL / SQL表中的数字将是TABLE1中的TABLE2_ID值. (例如,使用PL / SQL表而不是数组,因为表可以容纳不同数量的值,而如果我们使用数组,我们必须事先知道需要存储多少个数.我们事先不能知道特定语句会影响多少行,因此我们使用PL / SQL表).当达到AFTER EACH ROW时间点并且我们发现正在处理的语句是INSERT时,触发器就会继续并执行必要的更新到TABLE2,因为这不会导致问题.但是,如果正在执行DELETE,则触发器将TABLE1.TABLE2_ID保存到先前分配的PL / SQL表中.当最终到达AFTER STATEMENT时间点时,先前分配的PL / SQL表被迭代,并且对于找到的每个TABLE2_ID,执行适当的更新. Documentation here. 分享和享受. (编辑:上饶站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |