★PostgreSQLカンファレンス2024 12月6日開催/チケット販売中★
他のバージョンの文書 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9.6 | 9.5 | 9.4 | 9.3 | 9.2 | 9.1 | 9.0 | 8.4 | 8.3 | 8.2 | 8.1 | 8.0 | 7.4 | 7.3 | 7.2

Chapter 20. トリガ

Table of Contents
20.1. トリガの生成
20.2. トリガマネージャとの関係
20.3. データ変更時の可視性
20.4.

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

20.1. トリガの生成

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

トリガが生成される前に、トリガ関数は、引数をとらない、opaque型を返す関数として定義されていなければいけません。もし関数がCで書かれている場合、"version 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()という関数があります。