【実務・中級編】 トリガーの基礎 – PostgreSQL

データベースの「自動操縦」を極める:PostgreSQLトリガーの基礎と実践

こんにちは。現場で日々SQLと格闘している皆さん、お疲れ様です。

データベースを触っていると、「あ、このテーブルにデータが入った瞬間、自動的に別のテーブルにもログを書き込みたいな」とか、「特定のカラムが更新された時に、必ずタイムスタンプを更新し忘れないようにしたいな」なんて思うこと、ありますよね。

アプリケーション側で実装してもいいけれど、それだと「抜け漏れ」が怖い。そんな時、DBエンジニアとして頼りになるのが「トリガー(Trigger)」です。今回は、PostgreSQLにおけるトリガーの「勘所」を、現場目線で噛み砕いて解説します。

—

トリガーとは、DBの「お節介機能」である

トリガーを一言で言えば、「特定のイベント(INSERT, UPDATE, DELETEなど)をトリガーにして、あらかじめ定義した関数を自動で呼び出す仕組み」です。

アプリケーションのロジックに依存せず、DBの層で強制的に処理を走らせることができるため、データ整合性を守る最後の砦として非常に強力です。ただ、便利すぎて多用すると「なぜこのデータが変わったんだっけ?」というデバッグの迷宮に迷い込むこともあるので、使い所は慎重にいきましょう。

—

基本の構文:セットで覚える「関数」と「トリガー」

PostgreSQLのトリガーは、少し独特です。
まず「トリガーが呼ばれた時に実行する処理」を `FUNCTION` として定義し、その後に「いつ実行するか」という `TRIGGER` を定義します。

— 1. まずはトリガー用の関数を作る
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW(); — 更新されるレコードのupdated_atを現在時刻にする
RETURN NEW;
END;
$$ LANGUAGE plpgsql;

— 2. テーブルにトリガーを紐づける
CREATE TRIGGER trg_update_updated_at
BEFORE UPDATE ON users
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();

これだけで、`users` テーブルが更新されるたびに、勝手に `updated_at` が現在時刻に書き換わります。便利でしょう?

—

「いつ」動かすか?(BEFORE / AFTER / INSTEAD OF)

トリガーのタイミング選びは重要です。現場でよく使う3つを覚えておきましょう。

  • BEFORE: 処理の「前」です。データのバリデーション(不正な値のチェック)や、書き込む値の加工(先ほどのタイムスタンプ更新など)に使います。
  • AFTER: 処理の「後」です。INSERTされた後にログテーブルへ記録したり、外部システムへ通知を送ったりする際によく使います。データが確定しているのが強みですね。
  • INSTEAD OF: これは特殊です。主に「ビュー(View)」に対して使います。更新できないビューに対して、「もし更新されたら、裏で代わりにこの処理をしてね」という代行指示を出すイメージです。

—

「どの単位で」動かすか?(FOR EACH ROW / STATEMENT)

ここを意識しないと、パフォーマンスで痛い目を見ます。

  • FOR EACH ROW: 変更された「1行ごと」に実行されます。100行まとめてUPDATEしたら、トリガーも100回動きます。細かい制御ができる反面、重い処理を仕込むとDBが悲鳴を上げます。
  • FOR EACH STATEMENT: SQLの「命令ごと」に1回だけ実行されます。100行更新してもトリガーは1回です。更新のログを1行だけ残したい、といった場合にはこちらが適任です。

—

先輩からの実践的なアドバイス:気をつけるべき点

最後に、現場で設計する際に気をつけていることをいくつかシェアします。

1. 「ブラックボックス化」に注意:
トリガーは隠れたところで動くので、プロジェクトに新しく入った人が「なんでデータが書き換わったんだ?」と悩む原因になります。使うなら、運用ドキュメントには必ず記載してください。
2. パフォーマンスの罠:
トリガーの中で重いSELECT文や、外部APIを叩くような処理は厳禁です。DBのレスポンスが極端に落ちます。
3. 無限ループの罠:
トリガーの中で、自分がトリガーを起動させるような更新(UPDATE)を書くと、無限ループでプロセスが死にます。`NEW` を使って更新する際は、本当に変更が必要かチェックを入れるなど、慎重に書いてください。

—

まとめ

トリガーは、正しく使えばアプリケーション側のコードを劇的にシンプルにしてくれる「頼れる相棒」です。

まずは、`updated_at` の自動更新や、簡単な監査ログの記録あたりから触ってみてください。PostgreSQLのトリガーを使いこなせると、データ設計の幅がぐっと広がりますよ。

もし「こんな複雑なトリガーはどう書けばいいの?」という疑問があれば、いつでも聞いてくださいね。一緒に良いコードを書いていきましょう!

コメント

タイトルとURLをコピーしました