0

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

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'

我知道您可以通过删除触发器中的“每行”行来解决此问题,但我需要使用“旧”和“新”值,因此我需要“每行”代码。

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;
/
4

2 回答 2

1

触发器无法从触发它的表中进行选择。否则你会得到 ORA-04091: table XXXX is mutating, trigger/function may not see it。尽量不要在触发器中加入太多逻辑。

无论如何,我知道可以做一个全面的解决方案,但老实说我没有尝试过......,我知道你可以创建存储过程,创建一个作业并从触发器运行作业。

于 2014-03-12T05:47:28.150 回答
1

我认为您不需要在这两个 SELECTS 中引用 STORE_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;

第一个 SELECT 是完全错误的。我不知道您要做什么,但是该 SQL 将返回 0 行或所有行并尝试将其放入标量值中。

看起来您在第二个 SELECT(以及 INSERT)中也有同样的问题。

只需使用 NEW 或 OLD 中的 DVD_ID,而不是尝试从 STORE_COPY 中选择它。

于 2014-03-12T10:10:21.990 回答