2触发同时启动

时间:2014-09-18 12:24:10

标签: oracle plsql oracle11g plsqldeveloper

我有两张桌子

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',但这似乎根本不适用于触发器。有什么想法吗?

提前致谢: - )

3 个答案:

答案 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语句中,即如果列已更新,则触发器将触发,即使它已更新与它的价值相同。