ORA-04091 由于游标,表名在触发器中发生变化
Posted
技术标签:
【中文标题】ORA-04091 由于游标,表名在触发器中发生变化【英文标题】:ORA-04091 table name is mutating in trigger due to cursor 【发布时间】:2014-01-03 19:22:25 【问题描述】:因此,当我编译以下脚本时,它会引发变异表错误:
CREATE OR REPLACE TRIGGER SEND_MAIL
BEFORE DELETE
ON CATEGORIE
FOR EACH ROW
DECLARE
bodytext varchar2(100);
CURSOR getabonnee IS
SELECT CATEGORIEABONNEMENT.MAILABONNEEID, NAAM
FROM CATEGORIE
INNER JOIN CATEGORIEABONNEMENT ON CATEGORIEABONNEMENT.CATEGORIENAAM = CATEGORIE.NAAM
WHERE NAAM = :old.NAAM;
CURSOR getabonneeinfo(p_id CATEGORIEABONNEMENT.MAILABONNEEID%TYPE) IS
SELECT MAILABONNEE.VOORNAAM, MAILABONNEE.ACHTERNAAM, MAILABONNEE.EMAILADRES
FROM CATEGORIEABONNEMENT
INNER JOIN MAILABONNEE ON MAILABONNEE.ID = CATEGORIEABONNEMENT.MAILABONNEEID
WHERE MAILABONNEEID = p_id;
BEGIN
FOR cc IN getabonnee LOOP
FOR cc2 IN getabonneeinfo(cc.MAILABONNEEID) LOOP
bodytext := cc2.voornaam || cc2.achternaam || :old.NAAM;
EXECUTE IMMEDIATE bodytext;
SENDMAILABONNEE(bodytext, cc2.emailadres);
DELETE FROM CATEGORIEABONNEMENT
WHERE MAILABONNEEID = cc.MAILABONNEEID;
UPDATE NIEUWSBERICHT
SET CATEGORIENAAM = null
WHERE CATEGORIENAAM = :old.NAAM;
END LOOP;
END LOOP;
END;
/
savepoint deletecategory;
delete from Categorie where naam='Buitenland';
rollback to deletecategory;
我寻找此错误的解决方案,发现人们建议使用复合触发器。问题是由于某种原因,我的数据库软件 (Oracle SQL Developer) 无法将复合触发器识别为有效单元。我检查了我的 oracle 版本,我有 11g,所以我不太明白为什么它不起作用。有人有这个问题的解决方案吗?
【问题讨论】:
所以,您一定遇到了某种编译错误。请更具体。 这不是无限循环吗?在您的Delete from Categorie where naam='Buitenland'
from categorie 的触发器中,触发器用于删除之前的表类别。我相信系统会在更新之前递归调用触发器,从而进入无限循环。但是我对触发器的了解很薄弱。只是看起来像一个逻辑缺陷。
@OldProgrammer 当我使用复合触发器时,它会抛出错误 PLS-00103:在期望以下之一时遇到符号“FOR”:函数、编译指示、过程、之前、之后等。编译上面代码的错误是 ORA-04091: table name is mutating, trigger/function may not see it.
“Oracle SQL Developer”不是您的数据库软件——它只是 Oracle RDBMS 的接口。可能您使用的 RDBMS 版本不支持复合触发器。
不要从触发器所在的同一个表中选择/更新/删除,因为它处于更改状态,因此是“变异”。
【参考方案1】:
在您的第一个游标中,不要在查询中包含 CATEGORIE 表。触发器已经具有您要删除的行中所有列的值,因此将其更改为:
SELECT MAILABONNEEID
FROM CATEGORIEABONNEMENT
WHERE CATEGORIEABONNEMENT.CATEGORIENAAM = :old.NAAM;
【讨论】:
以上是关于ORA-04091 由于游标,表名在触发器中发生变化的主要内容,如果未能解决你的问题,请参考以下文章
ORA-04091: 表 JOSEP.EMP 正在变异,触发器/函数可能看不到它
ORA-04091:表正在变异,触发器/函数可能看不到它,ORA-06512:,ORA-06512:在“SYS.DBMS_SQL”,第 1721 行