1

子テーブルの値を (挿入または更新後に) 親テーブルに集計するトリガーを作成しようとしています。子テーブルCにはフィールドid, year, month, valueがあり、親にPid, year, value. 新しい行が C に挿入されるか、既存の行が更新されると、トリガーはその年のすべての月の値を合計し、その合計を の対応する行に書き込む必要がありPます。これが私がそれを実装した方法です:

CREATE OR REPLACE
TRIGGER tr__aggregation 
AFTER INSERT OR UPDATE ON C
FOR each row 
DECLARE

BEGIN


 MERGE INTO P o
            USING (SELECT id, year, sum(value) as val
                  FROM C 
                   WHERE id = :NEW.id
                   AND year = :NEW.year
                   GROUP BY id, year) n 
            ON (n.id = o.id AND n.year = o.year)
            WHEN NOT MATCHED THEN INSERT (o.id, o.year, o.value) 
                                  VALUES (n.id, n.year, n.value)
            WHEN MATCHED THEN UPDATE SET o.value = NVL(n.value, o.value);

EXCEPTION WHEN OTHERS THEN
    pck_util.pr_exception_info(TRUE);
    RAISE;
END;

何らかの理由で、このエラーが発生します: SQL Error: ORA-04091: table C is mutating, trigger/function may not see it

理由がわかりません。変更しようとしているわけではありませCP。ありがとうございました!

4

3 に答える 3

1

変更中にテーブルをSQL Error: ORA-04091: table C is mutating, trigger/function may not see itクエリするため、このエラーが発生します。この種のエラーを回避するには、トリガーのロジックをプロシージャにカプセル化し、必要に応じて実行するだけです。テーブルの代わりになるビューを作成することもできます。CSELECT ... FROM CAFTER INSERT OR UPDATE ON CP

Create or replace view P as
  select p.id
       , p.year
       , sum(nvl(c.value, 0)) value
    from P
    join C
      on (p.id = c.id and p.year = c.year)
   group by p.id
          , p.year 
于 2012-09-17T07:44:21.823 に答える
1

エラーは、変更テーブル Cをクエリしているという事実から発生します。

ドキュメントから:

変更テーブルとは、UPDATE、DELETE、または INSERT ステートメントによって変更されているテーブル、または DELETE CASCADE 制約の影響によって更新される可能性のあるテーブルです。

トリガー ステートメントを発行したセッションは、変更テーブルをクエリまたは変更できません。

エラーを回避する方法を示すこの記事を読むことができます。

個人的には、具体化されたビューを使用して集計を保存します。

于 2012-09-17T07:05:42.427 に答える
1

これは、移動中 (変更中) の C からの選択を使用して P を更新するためです。

より良い解決策は、マテリアライズド ビューを使用することです。

Create materialized view p
refresh fast on commit as
SELECT id, year, sum(value) as val
FROM C 
GROUP BY id, year;

Fly による構文がわかりません。おそらく、他の句が必要です。

更新: docsを読んでください。例 3 のように、ベース テーブルにマテリアライズド ビュー ログも必要です。

CREATE MATERIALIZED VIEW LOG ON C WITH SEQUENCE, ROWID
(id, year, value)
INCLUDING NEW VALUES;
于 2012-09-17T07:06:23.650 に答える