1つのテーブルに2つのトリガーがあります。 1つはINSERTで機能します。
_CREATE TRIGGER "get_user_name"
AFTER INSERT ON "field_data"
FOR EACH ROW EXECUTE PROCEDURE "add_info"();
_
これにより、テーブルの一部の値が更新されます。
そしてUPDATEの1つ(履歴テーブルを埋めるため):
_CREATE TRIGGER "set_history"
BEFORE UPDATE ON "field_data"
FOR EACH ROW EXECUTE PROCEDURE "gener_history"();
_
問題は、テーブルに新しい行を挿入すると、プロシージャ"add_info"()
が更新を行うため、2番目のトリガーが起動し、エラーで終了することです。
_ERROR: record "new" has no field "field1"
_
どうすればこれを回避できますか?
(トリガーロジックの明らかなエラーは別です。)
Postgres9.2以降では、関数 pg_trigger_depth()
トリガー @ Akashについてはすでに述べています トリガー自体の条件内 (トリガー関数の本体ではなく)、別のトリガーから呼び出されたときにトリガー関数が実行されないようにする(それ自体を含む-ループも防止する)。
これは通常、パフォーマンスが高く、シンプルでクリーンです。
CREATE TRIGGER set_history
BEFORE UPDATE ON field_data
FOR EACH ROW
WHEN (pg_trigger_depth() < 1)
EXECUTE PROCEDURE gener_history();
式pg_trigger_depth() < 1
は、トリガー関数に入る前に評価されます。したがって、最初の呼び出しでは0と評価されます。別のトリガーから呼び出された場合、値は高くなり、トリガー関数は実行されません。
挿入トリガー内から呼び出されたときに更新トリガーを実行したくない場合は、深度を返すpg_trigger_depth()
の条件でステートメントを囲むことができます別のトリガーから直接/間接的にトリガーを実行している場合、これは0にはなりません。
したがって、関数gener_history()
内で、次のようなことができます
IF pg_trigger_depth() = 1 THEN
.. your statements..
END IF;
次に別の例を示します。 http://www.depesz.com/2012/02/01/waiting-for-9-2-trigger-depth/
アプリからAFTER INSERT
トリガーを削除してadd_info
を呼び出します
AFTER INSERT
トリガーをBEFORE INSERT
に変更します