1

変異トリガーエラーに直面しています、

ここでは、tableAとtableBを使用している問題について説明します。

TableAは、2つの値'-'、'+'を保持できるempCheckedという列を保持します。
TableBは、2つの値'-'、'+'を保持できるmgrCheckedという列を保持します。

現在の要件は、empCheckedとmgrcheckedの両方のフィールドが同期している必要があることです。つまり、empCheckedが'+'に更新された場合、tableBでチェックインされたmgrは' +'に更新される必要があり、その逆も同様です。両方のフィールドのフロントエンドからの更新が可能です。

両方のテーブルにトリガーを作成しました。しかし、私はora-04091エラーに直面しています。

これを達成するためのアプローチを教えてください。

4

3 に答える 3

4

ミューティングテーブルエラーはコードの臭いです。ほとんどの場合、不適切なデータモデル、通常は不十分な正規化を示しています。

確かに、ここには悪いデータモデルがあります。2つの設定を持つテーブルに列があります。それはいいです。次に、同じ列を2番目のテーブルに追加し、2つを同期させます。この新しいコラムは完全に無意味です。その新しい列には、最初のテーブルのクエリから取得できない情報はありません。

そしてそれはORA-04091があなたに言っていることです。回避策の構築に非常に多くの時間を費やすことができますが、それはすべて無駄な努力になります。

于 2012-09-10T13:55:14.977 に答える
1

この種の同期にトリガーを使用する代わりに、TableBのすべてのデータ(mgrcheckedではない)+TableAのempChecked列を「含む」TableBという名前のビューを作成してみませんか。

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;
/

キーは使用しないでくださいFOR EACH ROW。これにより、テーブルがロックされます。


編集

  • これは、テーブルロックまたはORA-04091と競合しませんFOR EACH ROW。これは、トリガー条件(行トリガーではない)がないためです。つまり、トリガー本体は、更新アクション全体が終了した後にのみ実行されます。

  • inトリガー本体が0を返す場合、内部トリガー本体は実行されないため、これによって無限ループが発生することはありません。count(*)UPDATE

  • また、count(*)これはステートメントトリガーであり、使用できるものがないため、使用する必要が:new.emp_checkedあります。

  • 一般的なシナリオ:table_aの更新->トリガーtri_table_a->[トリガー]チェックカウント->[トリガー]更新table_b->トリガーtri_table_b->[トリガー]チェックカウント->完了。

  • この回答を投稿する前に、自分でこれを試しました。

于 2012-09-10T07:23:57.997 に答える