我有两张桌子
user_salary
-------------------------
| user_id | salary_p |
-------------------------
| 1 | 100 |
| 2 | 200 |
-------------------------
user_p_salary
------------------------
| user_id | salary_c |
-------------------------
| 1 | 100 |
| 2 | 200 |
-------------------------
user_salary通过UI使用,它有以下触发器:
create or replace trigger t$user_salary_aiu
after insert or update of salary_p
on user_salary
for each row
begin
update user_p_salary t
set t.salary_c = :new.salary_p,
where t.user_id = :new.user_id
end t$user_salary_aiu;
user_p_salary通过集成获取数据,它具有以下代码:
create or replace trigger t$user_p_salary_aiu
after insert or update of salary_c
on user_p_salary
for each row
begin
update user_salary t
set t.salary_p = :new.salary_c,
where t.user_id = :new.user_id
end t$user_p_salary_aiu;
现在的问题是,如果其中一个表获取数据,那么它会执行其触发器并更新另一个表中的数据。但是,另一个表上的触发器也会执行..这就像触发循环一样。
唯一的方法是使用execute immediate'change triggername disable',但这似乎根本不适用于触发器。有什么想法吗?
提前致谢: - )
答案 0 :(得分:2)
ORA-04091错误正是这里应该发生的。简单来说,你不能做你想做的事。考虑一下 - 你更新表#1,然后表#1上的触发器更新表#2,其触发器更新表#1,其触发器一遍又一遍地更新表#2。这是一个触发循环,Oracle不允许这种情况发生。规则是行触发器无法访问已在同一事务中更改(或“变异”)的表。有一些技术(特别是复合触发器)让你“解决”这个问题,但最好的方法是重新设计以消除这个问题。很抱歉成为坏消息的承担者。祝你好运。
答案 1 :(得分:1)
如何为每个名为BY_TRIGGER的表添加一列。
对于触发器外的更新或插入,您只需不指定此列。但是,在触发器中更新或插入时,传递值为1。
此外,在每个trigegr中,检查:new.BY_TRIGGER是否为1,如果是,则跳过插入/更新到另一个表。
答案 2 :(得分:1)
为什么不更新薪水,如果它不等于新值,例如
create or replace trigger t$user_salary_aiu
after insert or update of salary_p
on user_salary
for each row
begin
update user_p_salary t
set t.salary_c = :new.salary_p
where t.user_id = :new.user_id
and ( t.salary_c <> :new.salary_p
or (t.salary_c is null and :new.salary_p is not null)
or (t.salary_c is not null and :new.salary_p is null) );
end t$user_salary_aiu;
create or replace trigger t$user_p_salary_aiu
after insert or update of salary_c
on user_p_salary
for each row
begin
update user_salary t
set t.salary_p = :new.salary_c
where t.user_id = :new.user_id
and ( t.salary_p <> :new.salary_c;
or (t.salary_p is null and :new.salary_c is not null)
or (t.salary_p is not null and :new.salary_c is null) );
end t$user_p_salary_aiu;
注意:尽管文档的措辞如此,但dml_event_clause update of column
似乎意味着如果列包含在触发UPDATE
语句中,即如果列已更新,则触发器将触发,即使它已更新与它的价值相同。