PLSQL:变异表停止我的“更新前触发器”。怎么办?

PLSQL:变异表停止我的“更新前触发器”。怎么办?,plsql,triggers,mutating-table,Plsql,Triggers,Mutating Table,我终于编译了我的触发器,但现在我在执行相关更新时遇到了一个变异表错误: ORA-04091: table KEV.STORE_COPY is mutating, trigger/function may not see it ORA-06512: at "KEV.SOLD", line 5 ORA-04088: error during execution of trigger 'KEV.SOLD' 我知道您可以通过删除触发器中的“for each row”行来解决此问题,但我需要使用“old

我终于编译了我的触发器,但现在我在执行相关更新时遇到了一个变异表错误:

ORA-04091: table KEV.STORE_COPY is mutating, trigger/function may not see it
ORA-06512: at "KEV.SOLD", line 5
ORA-04088: error during execution of trigger 'KEV.SOLD'
我知道您可以通过删除触发器中的“for each row”行来解决此问题,但我需要使用“old”和“new”值,因此我需要“for each row”代码

CREATE OR REPLACE TRIGGER SOLD
BEFORE UPDATE OF STATUS ON STORE_COPY
FOR EACH ROW
DECLARE 
RENT_OR_SALE NVARCHAR2(6);
UPDATED_DVD_ID NUMBER(10);
BEGIN
SELECT (SELECT DVD_ID FROM STORE_COPY WHERE :NEW.STATUS != :OLD.STATUS) INTO      UPDATED_DVD_ID FROM DUAL;
SELECT (SELECT RENT_OR_SALE FROM DVD JOIN STORE_COPY ON STORE_COPY.DVD_ID = DVD.DVD_ID  WHERE DVD.DVD_ID = UPDATED_DVD_ID) INTO RENT_OR_SALE FROM DUAL;
IF :NEW.STATUS != :OLD.STATUS
THEN
IF :OLD.STATUS = 'Y'
THEN
IF :NEW.STATUS = 'N'
THEN
IF RENT_OR_SALE = 'S'
THEN
INSERT INTO SOLD VALUES(NULL, CURRENT_TIMESTAMP, (SELECT PRICE FROM DVD JOIN STORE_COPY  ON STORE_COPY.DVD_ID = DVD.DVD_ID WHERE :NEW.DVD_ID = UPDATED_DVD_ID), :NEW.DVD_ID);
END IF;
END IF;
END IF;
END IF;
END;
/

触发器无法从为其触发的表中选择。否则您将得到ORA-04091:表XXXX正在发生变异,触发器/函数可能看不到它。尽量不要在触发器中加入太多逻辑


无论如何,我知道有可能实现一个循环解决方案,但老实说,我没有尝试过…,我知道您可以创建存储过程、创建作业并从触发器运行作业。

我认为您不需要在以下两个选项中引用STORE\u COPY:

SELECT (SELECT DVD_ID FROM STORE_COPY WHERE :NEW.STATUS != :OLD.STATUS) INTO      UPDATED_DVD_ID FROM DUAL;
SELECT (SELECT RENT_OR_SALE FROM DVD JOIN STORE_COPY ON STORE_COPY.DVD_ID = DVD.DVD_ID  WHERE DVD.DVD_ID = UPDATED_DVD_ID) INTO RENT_OR_SALE FROM DUAL;
第一个选择完全错了。我不知道您试图做什么,但SQL将返回0行或所有行,并尝试将其转换为标量值

看起来在第二次选择和插入中也有相同的问题


只需使用“新”或“旧”中的DVD\u ID,而不是尝试从“存储副本”中选择它。

DVD\u ID“旧”或“新”是否只返回修改过的行?这正是我在这一轮中试图确保的:OLD是STORE\u COPY中的行,因为它在更新之前看起来是这样的:新的是它在更新后的样子。用一些程序替换了我所有的触发器。值得。