2017-05-22 10 views
0

私はtableAに挿入するときにトリガされる関数を設定しています。これは最初にtableBでエントリを作成し、次に外部キーが存在するtableC内にいくつかのエントリを作成しますtableBに関連しています。しかし、関数が実行を終了しない限り、tableBに存在しない外部キーフィールドの値をtableCに挿入しようとするため、エラーが発生します。関数のシーケンス結果PostgreSQL 9.5

関数内に、関数内に何らかの戻りを入れますが、関数を終了せずに残りの部分を実行する方法はありますか?次のようになり何か:

CREATE OR REPLACE FUNCTION trigger1() RETURNS trigger AS 
$BODY$ 
begin 
insert into tableB values (new.value); 
RETURN NEW; 
insert into tableC (id, fkey) values (new.something, new.value); 
RETURN NEW; 
end; 
$BODY$ 
LANGUAGE plpgsql; 

私は、彼らは両方の前に実行されているかもしれないので、成功せず、実行を注文するアルファベット順を使用して、2つの異なるトリガに機能を分離することを試みた...

ご存じですか?

おかげ

答えて

2

DEFERRABLE INITIALLY DEFERREDとしてTABLECの外部キーを宣言します。

the documentation:

DEFERRABLEから、これは制約を延期することが可能かどうかを制御

を遅延不可。遅延可能でない制約は、すべての コマンドの直後にチェックされます。遅延可能な制約のチェックは、トランザクションの終了時まで(SET CONSTRAINTSコマンドを使用して)延期することができます( )。 NOT DEFERRABLEがデフォルトです。現在、UNIQUE、PRIMARY KEY、 EXCLUDE、およびREFERENCES(外部キー)制約のみがこの句を受け入れます。 NOT NULLおよびCHECK制約は遅延可能ではありません。

Btw。関数本体の最初のRETURN NEW;は意味をなさない。

+0

感謝。私はこの問題の仕組みを理解するのが難しいです。外部キーを延期し、拘束力が尊重されていない場合はどうなりますか?それはエラーを起こすでしょうか?トランザクションの終了時に、トランザクション全体を「覚えて」キャンセルします。 –

+1

はい、制約の失敗時にエラーが発生し、トランザクションがロールバックされます。ただし、Expliciteトランザクションを使用する必要はありません。外部トランザクションがない場合、トリガー関数は単一のトランザクションそのものです。一般的には、トリガーで何かを変更することなく、期待どおりに動作します。 – klin

2

まず、関数の同じフロー内に2つのRETURN文を持つことは不可能です。

あなたの問題について、これを達成する方法はたくさんあります。そのうちの1つは、DEFERRABLE TRIGGER(トランザクションの終了時に評価される特別なタイプのトリガー)を使用しています。ような何か:

--Trigger function 
CREATE OR REPLACE FUNCTION trigger1() RETURNS trigger AS 
$BODY$ 
BEGIN 
    INSERT INTO "tableB" VALUES (new.value); 
    INSERT INTO "tableC" (id, fkey) VALUES (new.something, new.value); 
    RETURN NEW; 
END; 
$BODY$ 
LANGUAGE plpgsql; 

--Trigger raised at end of transaction. Take a look on 'CONSTRAINT' and 'INITIALLY DEFERRED' clauses. 
CREATE CONSTRAINT TRIGGER deferred_trigger_1 
    AFTER INSERT OR UPDATE 
    ON "tableA" 
    INITIALLY DEFERRED 
    FOR EACH ROW 
    EXECUTE PROCEDURE trigger1(); 

詳細情報here

+0

ありがとうございます。しかし、私はこれらのDEFERRABLE TRIGGERがどのように機能するのか見当たりません。この種のトリガーの構文の例を私に教えてください。 –

+0

@GuiOmClair私の更新答えを見てください。 –