Chapter 21. トリガ

Table of Contents
21.1. トリガの生成
21.2. トリガマネージャとの関係
21.3. データ変更時の可視性
21.4.

Postgresは様々なサーバサイド関数の インタフェースを持っています。サーバサイド関数は SQL, PLPGSQL, TCL, または C で書くことができます。トリガ関数は SQL を除く これらのどの言語でも使って書くことができます。 現バージョンでは、STATEMENT レベルのトリガーイベントはサポート されていませんので注意して下さい。 現在はタプルの INSERT、DELETE、 UPDATEの前( BEFORE )または後( AFTER )をトリガーイベントとして指定 できます。

21.1. トリガの生成

トリガイベントが発生すると、(エグゼキュータによって呼び出される) トリガマネージャは(後述の) TriggerData 情報構造体を 設定し、そのイベントを扱うトリガ関数を 呼び出します。

トリガが生成される前に、トリガ関数は、引数をとらない、 opaque 型を返す関数として作成されていなければなりません。 もし関数が C で書かれている場合、"バージョン1" 関数マネージャ インタフェースを使わなくてはいけません。

トリガを生成するための構文は次の通りです。

CREATE TRIGGER trigger [ BEFORE | AFTER ] [ INSERT | DELETE | UPDATE [ OR ... ] ]
    ON relation FOR EACH [ ROW | STATEMENT ]
    EXECUTE PROCEDURE procedure
     (args);
    
そこでの引数は下記です。

trigger

トリガ名は、トリガを削除する必要になった時にも使われます。 DROP TRIGGER コマンドの引数として使われます。

BEFORE, AFTER

関数がイベントが発生する前に呼ばれるのか後に呼ばれるのかを決定します。

INSERT, DELETE, UPDATE

次の要素は、どのコマンドのイベント(複数可)で関数を呼び出すか を決定します。複数のイベントを OR で区切って指定できます。

relation

リレーション名はどのテーブルにイベントを適用するかを決定します。

ROW, STATEMENT

FOR EACH 文はトリガを行が影響を受ける度に発行するか、 文全体が 終了する前(または後)に発行するかを決定します。

procedure

プロシージャ名は呼び出される関数を示します。

args

関数の引数は、関数に TriggerData 構造体の中に格納されて渡されます。 引数を関数に渡す目的は、同一関数の呼び出しによって要求仕様が 似ている異なるトリガを扱えるようにすることです。

また、procedureは異なるリレーションの トリガに使うこともできます。 (こういった関数は "汎用トリガー関数" と呼ばれます。)

上記の両機能を使う例として、片方に現在のユーザを、もう片方に現 時刻を格納した 2 つのフィールドの名前を引数としてとる汎用関数が あります。例えば、この関数を INSERT イベント時に使用すれば、 トランザクションテーブル内のレコードの作成を検出して、自動的に書 き込みを行なわせることができます。または、UPDATE イベント時に使 用すれば、"最終更新" 関数として使用することができます。

トリガ関数は呼び出したエグゼキュータに HeapTuple を返します。 これは INSERT、DELETE、UPDATE の後に発行されるトリガでは無視されますが、 BEFORE のトリガでは、以下を行なうことがで きます。

CREATE TRIGGER ハンドラによって初期化は行なわれないことに注意 して下さい。 このことは今後変更する予定です。また、同一リレーシ ョンの同一イベントに 対して複数トリガーが定義された場合は、トリガーの発行順は予測できません。 これも今後変更されるかもしれません。

トリガ関数が( SPI を使用して)SQL 問い合わせを処理する場合、 これらの問い合わせがトリガを再度発行することがあります。これ はカスケードされたトリガと呼ばれます。カスケードの段数に明確な 制限はありません。

INSERT によって発行されたトリガが同じリレーションに新しいタプル を挿入する場合、このトリガが再度発行されます。現状ではこの 場合の 同期(などの)機能は提供されていませんが、これも変更される可能性 があります。現段階では、レグレッションテストの中に、 自身への再帰 (カスケーディング)を停止させるための数個のテクニックを 使用した funny_dup17() という関数があります。