提问人:Turing 提问时间:11/16/2023 最后编辑:Thorsten KettnerTuring 更新时间:11/16/2023 访问量:22
如何在 oracle 中使用触发器插入后更新表时修复表突变异常?
How to fix table is mutating exception while updating the table after insert using trigger in oracle?
问:
我已经制作了一个触发器来更新表“SchemeComp”行,同时插入新行。我一次插入多个/批量行,但它抛出异常并且该行未插入。这是我得到的例外:
Error report -
ORA-04091: table ABC009.SchemeComp is mutating, trigger/function may not see it
ORA-06512: at "ABCS009.TrCreateParentChildRelation", line 3
ORA-04088: error during execution of trigger 'ABCS009.TrCreateParentChildRelation' `
这是我对触发器的查询:
CREATE OR REPLACE TRIGGER "TrCreateParentChildRelation"
AFTER INSERT ON "SchemeComp"
FOR EACH ROW
BEGIN
IF :NEW."ParentComponentCode" IS NOT NULL THEN
UPDATE "SchemeComp" sc1
SET sc1."ParentId" = (
SELECT sc2."Id"
FROM "SchemeComp" sc2
WHERE sc1."ParentComponentCode" = sc2."ComponentCode"
AND sc1."SchemeId" = sc2."SchemeId"
)
WHERE sc1."ParentComponentCode" IS NOT NULL
AND sc1."SchemeId" = :NEW."SchemeId";
END IF;
END;
/
下面是我的插入查询,我同时运行两个插入查询。
INSERT INTO "SchemeComp" ("ParentId", "ComponentCode", "ParentComponentCode", "ComponentName", "SchemeId", "EntryDate", "IsActive", "CreatedBy", "IP")
VALUES (null, 'B', null, 'Tribal Area Sub Plan', '0R55', SYSTIMESTAMP, '1', 'BANKADMIN002', '::1');
INSERT INTO "SchemeComp" ("ParentId", "ComponentCode", "ParentComponentCode", "ComponentName", "SchemeId", "EntryDate", "IsActive", "CreatedBy", "IP")
VALUES (null, 'B.1', 'B', 'Recurring', '0R55', SYSTIMESTAMP, '1', 'BANKADMIN002', '::1');
答:
1赞
Littlefoot
11/16/2023
#1
您不能直接(或从中选择值)要插入行的表,因为它 - 正如错误所说 - 正在变异。update
但是,如果您重写触发器,以便首先选择所需的值,然后更新它,那么它应该没问题。 像这样:
CREATE OR REPLACE TRIGGER "TrCreateParentChildRelation"
BEFORE INSERT
ON "SchemeComp"
FOR EACH ROW
DECLARE
l_parentid "SchemeComp"."ParentId"%TYPE;
BEGIN
IF :NEW."ParentComponentCode" IS NOT NULL
THEN
SELECT sc2."Id"
INTO l_parentid
FROM "SchemeComp" sc2
WHERE sc2."ComponentCode" = :new."ParentComponentCode"
AND sc2."SchemeId" = :new."SchemeId";
:new."ParentId" := l_parentid;
END IF;
END;
评论
1赞
Thorsten Kettner
11/16/2023
我看到这被接受了,并对此感到惊讶。触发器是在每行之前还是之后都没有关系。由于插入,表正在发生变化。单个 insert 语句可以任意顺序插入多行,因此我们不能查询表,因为结果不会是确定性的。也许这恰好有效,只要我们只插入单行,否则就会失败。我不知道。
1赞
Littlefoot
11/16/2023
啊!傻我,@Thorsten!我什至没有注意到它大约是同一张桌子!相反,我关注的是混合字母大小写。你是对的,除非插入单行,否则这是行不通的。经过一些测试后,我们将看到图灵说了什么。如果事实证明这个答案是无用的,我会删除它。
0赞
Turing
11/16/2023
@Littlefoot这很好用!谢谢。
0赞
Littlefoot
11/16/2023
别客气。
评论