PostgreSQL トリガー

PostgreSQL トリガーはデータベースのコールバック関数であり、指定されたデータベースイベントが発生したときに自動的に実行・呼び出しされます。

以下は PostgreSQL トリガーに関するいくつかの重要なポイントです:

  • PostgreSQL トリガーは次の場合に発動できます:

    • 操作を実行する前(制約をチェックし、挿入・更新・削除を試みる前)。
    • 操作を実行した後(制約をチェックし、挿入・更新・削除が完了した後)。
    • 更新操作(ビューに対して挿入、更新、削除を行う場合)。
  • トリガーの FOR EACH ROW 属性はオプションです。これを選択すると、操作が行を変更するたびに1回呼び出されます。逆に、FOR EACH STATEMENT を選択すると、変更された行数に関係なく、各ステートメントでトリガーが1回実行されます。

  • WHEN 句とトリガー操作は、NEW.column-name および OLD.column-name を参照することで、挿入、削除、更新の際に各行の要素にアクセスできます。ここで column-name は、トリガーが関連付けられているテーブルの列の名前です。

  • WHEN 句が存在する場合、PostgreSQL ステートメントは WHEN 句が成立する行に対してのみ実行されます。WHEN 句がない場合、PostgreSQL ステートメントはすべての行で実行されます。

  • BEFORE または AFTER キーワードは、トリガーアクションをいつ実行するかを決定します。関連する行の挿入、変更、削除の前か後かを決定します。

  • 変更対象のテーブルは、トリガーが追加されているテーブルまたはビューと同じデータベース内に存在する必要があり、database.tablename ではなく tablename のみを使用する必要があります。

  • 制約トリガーを作成するときは、制約オプションを指定します。これは通常のトリガーと同じですが、この制約を使用してトリガーが発動するタイミングを調整できます。制約トリガーによって実装された制約が違反されると、例外がスローされます。

構文

トリガーを作成するときの基本構文は次のとおりです:

CREATE  TRIGGER trigger_name [BEFORE|AFTER|INSTEAD OF] event_name
ON table_name
[
 -- 触发器逻辑....
];

ここで、event_name は、指定されたテーブル table_name に対する INSERT、DELETE、UPDATE のデータベース操作です。テーブル名の後に FOR EACH ROW をオプションで指定できます。

以下は、UPDATE 操作でテーブルの1つ以上の指定列に対してトリガーを作成する構文です:

CREATE  TRIGGER trigger_name [BEFORE|AFTER] UPDATE OF column_name
ON table_name
[
 -- 触发器逻辑....
];

例

新しく作成した COMPANY テーブル(既に存在する場合は削除して再作成)に挿入される各レコードについて監査証跡を維持したいと仮定しましょう:

サンプルdb=# CREATE TABLE COMPANY(
   ID INT PRIMARY KEY     NOT NULL,
   NAME           TEXT    NOT NULL,
   AGE            INT     NOT NULL,
   ADDRESS        CHAR(50),
   SALARY         REAL
);

監査証跡を維持するために、AUDIT という名前の新しいテーブルを作成します。COMPANY テーブルに新しいレコードが追加されるたびに、ログメッセージがそのテーブルに挿入されます。

サンプルdb=# CREATE TABLE AUDIT(
   EMP_ID INT NOT NULL,
   ENTRY_DATE TEXT NOT NULL
);

ここで、ID は AUDIT レコードの ID、EMP_ID は COMPANY テーブルの ID、DATE は COMPANY でレコードが作成されたときのタイムスタンプを保持します。それでは、COMPANY テーブルにトリガーを作成しましょう:

サンプルdb=# CREATE TRIGGER example_trigger AFTER INSERT ON COMPANY FOR EACH ROW EXECUTE PROCEDURE auditlogfunc();

auditlogfunc() は PostgreSQL のプログラムで、その定義は次のとおりです:

CREATE OR REPLACE FUNCTION auditlogfunc() RETURNS TRIGGER AS $example_table$
   BEGIN
      INSERT INTO AUDIT(EMP_ID, ENTRY_DATE) VALUES (new.ID, current_timestamp);
      RETURN NEW;
   END;
$example_table$ LANGUAGE plpgsql;

では、COMPANY テーブルにデータを挿入してみましょう:

サンプルdb=# INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) VALUES (1, 'Paul', 32, 'California', 20000.00 );

このとき、COMPANY テーブルに1つのレコードが挿入されました:

同時に、AUDIT テーブルにもレコードが挿入されました。COMPANY テーブルに挿入するときにトリガーを作成したためです。同様に、必要に応じて更新時や削除時のトリガーも作成できます:

emp_id |          entry_date
--------+-------------------------------
      1 | 2013-05-05 15:49:59.968+05:30
(1 row)

トリガーの一覧表示

pg_trigger テーブルから現在のデータベースのすべてのトリガーを一覧表示できます:

サンプルdb=# SELECT * FROM pg_trigger;

特定のテーブルのトリガーを一覧表示したい場合は、構文は次のとおりです:

サンプルdb=# SELECT tgname FROM pg_trigger, pg_class WHERE tgrelid=pg_class.oid AND relname='company';

結果は次のとおりです:

 tgname
-----------------
 example_trigger
(1 row)

トリガーの削除

トリガーを削除する基本構文は次のとおりです:

drop trigger ${trigger_name} on ${table_of_trigger_dependent};

この記事の上記の company テーブル上のトリガー example_trigger を削除するコマンドは次のとおりです:

drop trigger example_trigger on company;
その他の拡張