web-dev-qa-db-ja.com

ORA-04082:NEWまたはOLD参照は表レベルのトリガーでは許可されません

it perという名前のテーブルがあります。 perテーブルには、「fl1」という名前のフィールドと「fl2」という名前の別のフィールドがあります。レコードを更新するときに、「fl1」の値が変更されたかどうかを確認します。値が変更された場合、「fl1」の新しい値で「fl2」列を更新します。

このトリガーを思いついた

CREATE OR REPLACE TRIGGER Flag
AFTER INSERT OR UPDATE on per
REFERENCING NEW AS NEW OLD AS OLD
BEGIN
  If :New.fl1 != :Old.fl1 Then
        :New.fl2:= :new.fl1;
  End If;
END;

実行すると「ORA-04082:テーブルレベルトリガーで許可されていない新しいまたは古い参照」が表示されます

私が考えていたもう1つのオプション(効率的かどうかはわかりません)は、「fl1」の値が変更されたかどうかに関係なく、「fl2」の値を「fl1」の値で更新することです。

[〜#〜] update [〜#〜]

「For Each Row」を追加し、「BEFORE INSERT OR UPDATE」の「AFTER INSERT OR UPDATE」を変更しました。動作しています。

CREATE OR REPLACE TRIGGER Flag
BEFORE INSERT OR UPDATE on per
REFERENCING NEW AS NEW OLD AS OLD

FOR EACH ROW
BEGIN
If :New.fl1 != :Old.fl1 Then
   :New.fl2:= :new.fl1;
End If;
END;
23
Mark Marina

DMLトリガーは、テーブルレベルまたは行レベルとして定義されます。

テーブルレベルのトリガーは、テーブルの各操作に対して1回起動します。したがって、30行を更新する場合、テーブルトリガーに関する限り1つの操作になります。テーブルトリガーには、どの行が変更されているかについての洞察はありませんが、操作が実行されたという事実を記録するために使用できます。

この場合、行レベルのトリガーが必要です。これには、トリガー定義に「FOR EACH ROW」を含める必要があります。 「REFERENCING」句は、新しい行と古い行の参照方法を変更したくない場合はオプションです。

http://docs.Oracle.com/cd/B28359_01/appdev.111/b28370/triggers.htm#BABCIBBJ

ただし、ここでの演習のポイントがわからない。 fl2ではなくfl1を参照することを検討しましたか?

23
David Aldridge

最終的な作業コード:

CREATE OR REPLACE TRIGGER Flag
BEFORE INSERT OR UPDATE on per
REFERENCING NEW AS NEW OLD AS OLD

FOR EACH ROW
BEGIN
If :New.fl1 != :Old.fl1 Then
   :New.fl2:= :new.fl1;
End If;
END;
4
Mark Marina