1

我正面临变异触发错误,

我将在这里描述我使用 tableA 和 tableB 的问题。

TableA 包含一个名为 empChecked 的列,它可以包含 2 个值“-”、“+”。
TableB 包含一个名为 mgrChecked 的列,它可以包含 2 个值“-”、“+”。

当前要求是 empChecked 和 mgrchecked 中的两个字段必须同步。我的意思是,如果 empChecked 更新为“+”,那么在 tableB 中签入的经理必须更新为“+”,反之亦然。两个字段都可以从前端进行更新。

我在两个表上都创建了触发器。但我面临 ora-04091 错误。

请建议我任何方法来实现这一目标?

4

3 回答 3

4

变异表错误是代码异味。它几乎总是指向一个糟糕的数据模型,通常是标准化不足。

当然,这里有一个糟糕的数据模型。您的表格中有一个具有两个设置的列。没关系。现在您想将同一列添加到第二个表并保持两者同步。这个新专栏完全没有意义。该新列中没有可用的信息,而不是您无法通过查询第一个表获得的信息。

这就是 ORA-04091 告诉你的。您可以花费大量时间来构建解决方法,但这都是浪费精力。

于 2012-09-10T13:55:14.977 回答
1

与其使用触发器进行这种同步,为什么不创建一个名为 TableB 的视图,它将“包含”来自 TableB 的所有数据(不是 mgrchecked)+ 来自 TableA 的 empChecked 列像这样

create or replace view TAbleB as
  select t1.id
       , t1.Column2
       , ... 
       , t1.ColumnN
       , t.empChecked
    from TableA t
       , TableB t1
   where t.id = t1.id
于 2012-09-10T08:41:36.903 回答
-1

您对细节有点不清楚,但我认为这会有所帮助(假设您在两个表上都有一个 ID 列)

CREATE TRIGGER tri_table_a
    AFTER UPDATE ON table_a
DECLARE
    hits NUMBER :=0;
BEGIN
    SELECT count(*) INTO hits FROM table_a a INNER JOIN table_b b ON (a.id=b.id) WHERE a.emp_checked<>b.mgr_checked;
    IF hits>0 THEN
        UPDATE table_b b SET mgr_checked=(SELECT emp_checked FROM table_a a WHERE a.id=b.id);
    END IF;
END;
/

CREATE TRIGGER tri_table_b
    AFTER UPDATE ON table_b
DECLARE
    hits NUMBER :=0;
BEGIN
    SELECT count(*) INTO hits FROM table_a a INNER JOIN table_b b ON (a.id=b.id) WHERE a.emp_checked<>b.mgr_checked;
    IF hits>0 THEN
        UPDATE table_a a SET emp_checked=(SELECT mgr_checked FROM table_b b WHERE a.id=b.id);
    END IF;
END;
/

关键是 don't use FOR EACH ROW,这会导致表锁。


编辑

  • 这不会与 table lock 或 ORA- 04091冲突,因为没有FOR EACH ROWin trigger 条件(也不是row trigger),这意味着触发器主体只会在整个更新操作完成后执行;

  • 不会导致死循环,因为当count(*)in trigger body返回0时,UPDATE不会执行inside trigger body;

  • 另外,count(*)必须使用,因为这是一个语句触发器并且没有:new.emp_checked可用的;

  • 一般场景:更新table_a -> 触发tri_table_a -> [trigger]check count -> [trigger]update table_b ->triggers tri_table_b -> [trigger]check count -> done。

  • 在发布此答案之前,我自己尝试了这一点。

于 2012-09-10T07:23:57.997 回答