PostgreSQL 9.0.0文書
前のページ | 巻戻し |  | 早送り | 次のページ

# CREATE TRIGGER

## 名前

CREATE TRIGGER -- 新しいトリガを定義する

## 概要

    CREATE TRIGGER name { BEFORE | AFTER } { event [ OR ... ] }
        ON table [ FOR [ EACH ] { ROW | STATEMENT } ]
        [ WHEN ( condition ) ]
        EXECUTE PROCEDURE function_name ( arguments )

## 説明

`CREATE TRIGGER`は新しいトリガを作成します。 作成したトリガは指定したテーブルと関連付けられ、特定のイベントが発生した時に指定した関数`function_name`を実行します。

トリガでは、起動のタイミングとして、行への操作が開始される前（制約条件のチェックと`INSERT`、`UPDATE`または`DELETE`が行われる前）、あるいは、操作が完了した後（制約条件がチェックされ、`INSERT`、`UPDATE`または`DELETE`が完了した後）のいずれかを指定することができます。 イベントの前にトリガが起動する場合、そのトリガは対象行に対する操作を省略したり、（`INSERT`と`UPDATE`の操作時のみ）挿入する行を変更したりすることができます。 イベントの後にトリガが起動する場合、他のトリガの影響を含む全ての変更が、トリガに対して"可視"状態となります。

`FOR EACH ROW`付きのトリガは、その操作によって変更される行ごとに1回ずつ呼び出されます。 例えば、10行に影響を与える`DELETE`操作は、対象リレーション上の`ON DELETE`トリガを、行が削除される度に1回ずつ、個別に10回呼び出すことになります。 反対に、`FOR EACH STATEMENT`付きのトリガは、その操作によって何行変更されたかにかかわらず、任意の操作ごとに1回のみ実行されます （変更対象が0行となる操作でも、適用できる`FOR EACH STATEMENT`トリガがあれば実行されます）。

さらに、`FOR EACH STATEMENT`のみですが、トリガを`TRUNCATE`で発行するように定義することができます。

またトリガ定義では、トリガを発行すべきかどうかを判定する、論理値の`WHEN`条件を指定することができます。 行レベルのトリガでは、`WHEN`条件は行の列の古い値、新しい値、またはその両方で検証することができます。 文レベルのトリガでも`WHEN`条件を持たせることができますが、条件としてテーブル内の何らかの値を参照することができませんので、この機能はあまり有用ではありません

同一イベントに同じ種類の複数のトリガが定義された場合、名前のアルファベット順で実行されます。

`SELECT`はまったく行を変更しないため、`SELECT`トリガを作成することはできません。 この場合は、ルールやビューの方が適しています。

トリガに関するより詳細については、第36章を参照してください。

## パラメータ

`name`

  新しいトリガに付与する名前です。 同じテーブルの他のトリガと異なる名前にする必要があります。

`BEFORE`
`AFTER`

  関数の呼び出しをイベントの前に行うか後に行うかを決定します。

`event`

  `INSERT`、`UPDATE`、`DELETE`、 `TRUNCATE`のいずれかが入ります。 このパラメータは、トリガを起動するイベントを指定します。 `OR`を使用して、複数のイベントを指定することができます。

  `UPDATE`トリガでは、以下の構文を使用して列リストを指定することができます。

      UPDATE OF column_name1 [, column_name2 ... ]

  このトリガは更新対象として列挙された列のいずれか少なくとも1つの列が指定された場合に発行されます。

`table`

  トリガを作成するテーブルの名前です（スキーマ修飾名も可）。

`FOR EACH ROW`
`FOR EACH STATEMENT`

  このパラメータは、トリガプロシージャを、トリガイベントによって影響を受ける行ごとに1回起動するか、SQL文ごとに1回のみ起動するかを指定します。 どちらも指定されない場合は、`FOR EACH STATEMENT`がデフォルトです。

`condition`

  トリガ関数を実際に実行するか否かを決定する論理式です。 `WHEN`が指定された場合、`condition`が`true`を返す場合のみ関数が呼び出されます。 `FOR EACH ROW`トリガでは、`WHEN`条件で、それぞれ`OLD.`column_name``、`NEW.`column_name``と記述することで、古い行値、新しい行値、またはその両方の列を参照することができます。 当然ながら`INSERT`トリガでは`OLD`を参照することはできませんし、`DELETE`トリガでは`NEW`を参照することはできません。

  現時点では`WHEN`条件に副問い合わせを含めることはできません。

`function_name`

  ユーザが提供する関数です。この関数は、引数を取らず`trigger`型を返すよう定義します。トリガが起動した時に実行されます。

`arguments`

  トリガ実行時に関数に渡される引数をカンマで区切ったリストです。このパラメータは省略可能です。 引数として指定するのは、リテラル文字列定数です。 単純な名前および数値定数を記述できますが、全て文字列に変換されます。 関数内でこれらの引数にアクセスする方法について調べるためには、トリガ関数を実装した言語の説明を参照してください。 通常の関数引数とは異なる場合があります。

## 注釈

テーブルにトリガを作成するには、ユーザがそのテーブルに対し`TRIGGER`権限を持っている必要があります。

トリガを削除するためにはDROP TRIGGERを使用してください。

列指定のトリガ（`FOR UPDATE OF `column_name``）は、列挙された列のいずれかかが`UPDATE`コマンドの`SET`リスト内に対象として指定された場合に発行されます。 `BEFORE UPDATE`トリガにより行の内容になされた変更が考慮されないため、トリガが発行されない場合であっても、列の値を変更することができます。 反対に、`UPDATE ... SET x = x ...`のようなコマンドは、列の値が変更されていない場合であっても、`x`列に対するトリガは発行されます。

`BEFORE`トリガにおいて`WHEN`条件は関数が実行される、またはされそうな場合のみ評価されます。 このため`WHEN`の使用はトリガ関数の先頭で同一の条件を試験することと実質違いはありません。 この条件で確認できる`NEW`行が現在の値であり、それまでのトリガで変更されている可能性があることに、特に注意して下さい。 また`BEFORE`トリガの`WHEN`条件では、まだ設定されていませんので、`NEW`行のシステム列(`oid`など)を検査することができません。

`AFTER`トリガにおいて、`WHEN`条件は行の更新を行った直後に評価され、文の最後でトリガを発行するためにイベントを保持すべきかどうかを決定します。 このため`AFTER`トリガの`WHEN`条件は真を返さない場合、イベントを保持する必要もありませんし、文の最後の行を再度取り出す必要もありません。 これにより、トリガをわずかな行のみに対して発行する必要がある場合、多くの行を変更する文を非常に高速にすることができます。

PostgreSQL 7.3より前のバージョンでは、トリガ関数の戻り値の型を、`trigger`型ではなくプレースホルダである`opaque`型として宣言する必要がありました。 古いダンプファイルのロードをサポートするため、`CREATE TRIGGER`では`opaque`型を返すよう宣言された関数を受け入れます。 しかし、注意を促すメッセージを表示し、宣言された関数の戻り値型を`trigger`に変換します。

## 例

`accounts`テーブルの行が更新される直前に`check_account_update`関数を実行します。

    CREATE TRIGGER check_update
        BEFORE UPDATE ON accounts
        FOR EACH ROW
        EXECUTE PROCEDURE check_account_update();

上と同じです。 しかし、`balance`列が`UPDATE`コマンドの対象として使用された場合のみ実行されます。

    CREATE TRIGGER check_update
        BEFORE UPDATE OF balance ON accounts
        FOR EACH ROW
        EXECUTE PROCEDURE check_account_update();

以下の構文では、`balance`列が実際に変更された場合のみ関数が実行されます。

    CREATE TRIGGER check_update
        BEFORE UPDATE ON accounts
        FOR EACH ROW
        WHEN (OLD.balance IS DISTINCT FROM NEW.balance)
        EXECUTE PROCEDURE check_account_update();

何か変更された場合のみに`accounts`の更新のログを取る関数を呼び出します。

    CREATE TRIGGER log_update
        AFTER UPDATE ON accounts
        FOR EACH ROW
        WHEN (OLD.* IS DISTINCT FROM NEW.*)
        EXECUTE PROCEDURE log_account_update();

項36.4には、C言語で作成されたトリガ関数の完全な例があります。

## 互換性

PostgreSQLにおける`CREATE TRIGGER`文は標準SQLのサブセットを実装したものです ただし、PostgreSQLには、次の機能がありません。

- SQLでは、"old"や"new"、トリガによって起動する動作の定義が使用するテーブルに、別名を定義することができます。 （例えば、`CREATE TRIGGER ... ON tablename REFERENCING OLD ROW AS somename NEW ROW AS othername ...`）。 PostgreSQLでは、複数のユーザ定義言語でトリガプロシージャを作成できるので、データへのアクセスは言語固有の方法で扱われます。

- PostgreSQLでは、トリガ動作として、1つのユーザ定義関数の実行しか認めていません。 標準では、他のSQLコマンドを複数実行させることができます。 例えば、トリガ動作として`CREATE TABLE`を実行させることも可能です。 この制限を回避する方法は簡単です。必要なコマンドを実行するユーザ定義関数を作成すればよいのです。

SQLでは、複数のトリガは、作成時刻順に起動すべきであると規定しています。 PostgreSQLでは名前順であり、より簡単に判断することができます。

SQLでは、数珠繋ぎの削除に対する`BEFORE DELETE`は、数珠繋ぎの`DELETE`が完了した後に発行するものと規定しています。 PostgreSQLでは、`BEFORE DELETE`は常に削除操作よりも後に行われます。 この方がより一貫性があると考えています。 また、参照整合性に関する動作により引き起こる更新を実行している間に、`BEFORE`トリガが行を更新し、更新を妨げるような場合の動作は予測できません。 これは、制約違反となるかもしれませんし、参照整合性制約に合わないデータを格納してしまうかもしれません。

`OR`を使用して単一トリガに複数の動作を指定する機能は、標準SQLに対するPostgreSQLの拡張です。

`TRUNCATE`でのトリガ発行機能は標準SQLに対するPostgreSQLの拡張です。

## 関連項目

CREATE FUNCTION, ALTER TRIGGER, DROP TRIGGER

前のページ | ホーム | 次のページ
CREATE TEXT SEARCH TEMPLATE | 上に戻る | CREATE TYPE