我有三个表: A 和 B 关系是 A 可以有很多 B 所以 B 引用 A.id 作为其列之一
Table A
|id|date|...
Table B
|id|A_id|...
我在表 A 上创建了一个 Oracle 触发器,以便在更新它时更新一个 A_Mod 表。
这个触发器是
CREATE OR REPLACE TRIGGER TR_A_INSERT_UPDATE
AFTER INSERT OR UPDATE ON A
FOR EACH ROW
BEGIN
INSERT INTO A_Mod values(..., :new.date, ...)
END;
这很好用:)
我的问题是为表 B 创建触发器。
触发器是:
CREATE OR REPLACE TRIGGER TR_B_INSERT_UPDATE
AFTER INSERT OR UPDATE ON B
FOR EACH ROW
DECLARE
ts TIMESTAMP;
BEGIN
SELECT aa.date INTO ts FROM B bb
INNER JOIN A aa ON a.id = bb.A_id
WHERE bb.id = :new.id;
INSERT INTO A_Mod values(..., :new.date, ...)
END;
此触发器正在读取表 B 中更新行的 ID,然后从表 A 中的相应行获取日期。然后尝试将其插入 A_Mod
问题是我得到一个变异错误
Error report:
SQL Error: ORA-04091: table B is mutating, trigger/function may not see it
ORA-06512: at "TR_B_INSERT_UPDATE", line 5
ORA-04088: error during execution of trigger 'TR_B_INSERT_UPDATE'
04091. 00000 - "table %s.%s is mutating, trigger/function may not see it"
*Cause: A trigger (or a user defined plsql function that is referenced in
this statement) attempted to look at (or modify) a table that was
in the middle of being modified by the statement which fired it.
*Action: Rewrite the trigger (or function) so it does not read that table.
查看文档,我可以通过删除该FOR EACH ROW
行并让触发器在每个语句而不是每行触发一次来消除此错误。不幸的是,我使用的是 ORM 映射器,所以不要控制更新是如何发生的。我认为有时更新可能会覆盖多行。
文档说了一些关于创建临时表的内容,但我不确定这会有什么帮助。我是否必须在触发器内创建一个临时表,在这个临时表上创建一个触发器,然后更新 A_Mod,在触发触发器时更新这个临时表,然后删除之后的所有内容?
非常感谢任何提示。
谢谢