2009-04-02 28 views
15

トリガの再帰的な実行を防ぐ方法は?私は、アカウントのチャートで「ツリー可能」な説明を作成したいとしましょう。だから私は新しいレコードが挿入/更新されたときに、親レコードのdown_qtyを更新するので、更新トリガーが再帰的にトリガーされます。 -PostgreSQLの再帰トリガを防止する

は今、私のコードは大丈夫です、私はUPDATEトリガーの最初の行にこれを置く:

-- prevents recursive trigger 
if new.track_recursive_trigger <> old.track_recursive_trigger then 
    return new; 
end if; 

そして、私は親レコードの数量を更新する必要がある場合、これは私のトリガーからのサンプルコードです:

update account_category set 
    track_recursive_trigger = track_recursive_trigger + 1, -- i put this line to prevent recursive trigger 
    down_qty = down_qty - (old.down_qty + 1) 
where account_category_id = m_parent_account; 

新しいフィールドを導入せずにPostgreSQLで再帰トリガを検出する方法があると思っています。これはMSSQLのtrigger_nestlevelに類似しています。

[EDIT]ツリー内部

Iループ、私は戻って、そのルートに各account_categorydown_qtyまでバブルする必要があります。たとえば、新しいアカウントカテゴリを挿入すると、account_categoryという親のを増やす必要があります。同様に、アカウントカテゴリの親をaccount_categoryに変更すると、account_categoryの前の親のdown_qtyを減らす必要があります。account_category私はできると思いますが、私はPostgreSQLに再帰トリガーをさせません。トリガ再帰深度レベルが16レベルまでしか制限されていないところでMSSQLを使用しました。

+1

私はあなたがどちらかを持っていない限り、再帰呼び出しの危険性がない限り、もう少し詳しく説明する必要があると思います:自分の親であるレコード、またはあなたのツリーの中のループ(ツリーではない)。 –

答えて

6

pgでは、トリガーの再帰を追跡する必要があります。

トリガ機能は、これらのコマンドをコマンド SQLを実行した場合 火が再びトリガすることがあります。これは、 カスケードトリガーと呼ばれます。直接 のカスケード数の制限はありません レベルです。カスケードで を呼び出すと、 トリガの再帰的な呼び出しが発生する可能性があります。たとえば、INSERT トリガーが、同じテーブルの に追加の行を挿入して、INSERTトリガー を再度発生させるコマンドを実行する可能性があります。このようなシナリオでは、 の無限再帰を回避するのは、トリガー プログラマーの責任です。あなたがその特定のテーブルの上にトリガを無効にし、最後にそれらを再度有効(と予想される前に例外が実行を終了していないことを確認することができますトリガの定義のbegginingで

http://www.postgresql.org/docs/8.3/static/trigger-definition.html

3

! )。これには多くの深い穴がありますが、軽い実装ではうまくいくかもしれません。この実装では、トリガーを無効にするための権限も必要です。

+0

これは動作しません:このセッションでアクティブなクエリで使用されているため、ALTER TABLE "trigger_table"を使用できません。 –

54

これは私がPostgreSQL 9.2で行っていることですが、私はこのアプローチが文書化されていないことを認めなければなりません。トリガー内の元のコールとネストされたコールを区別するために使用する関数pg_trigger_depth()documented hereがあります。

CREATE TRIGGER trg_taxonomic_positions 
AFTER INSERT OR UPDATE OF taxonomic_position 
ON taxon_concepts 
FOR EACH ROW 
WHEN (pg_trigger_depth() = 0) 
EXECUTE PROCEDURE trg_taxonomic_positions() 
+0

nice find!これは、他の厄介な問題のホストを解決するのに役立ちます。 –

+0

スコア!完璧なソリューション、ありがとう! – theory

+4

ブリリアント!残念ながら、この関数は9.1には存在しません:(私はそれが置き換えられているのだろうかと思っています... – mvp

2

無制限の再帰を避けるには、 my answer hereを参照してください。他の人がコメントしたように、データ構造が真のツリー(ルートは親を持たない)であり、再帰はは常にルートでを停止します。 ノードの場合、親が1つだけの場合ポインタの場合、無限再帰の唯一の方法はループが存在する場合です。 (私のリンクのメソッドは、いずれのノードにもアクセスします最大で

関連する問題