メインコンテンツへスキップ

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples on this page work on VillageSQL. Install Now →
トリガーは、行が挿入、更新、または削除されたときに自動的に実行される SQL です。MySQL はデータ変更の前または後にトリガーを起動し、書き込まれる行の値にアクセスできるようにします。

トリガーの作成

実用的な例 — すべての価格変更を記録します。
トリガーを削除します。
現在のデータベースのすべてのトリガーを一覧表示します。

BEFORE と AFTER

BEFORE INSERT トリガーはデフォルト値を設定したり、不正なデータを拒否したりできます。AFTER INSERT トリガーは、挿入が成功した後に監査レコードを書き込めます。

NEW と OLD の参照

BEFORE トリガーで NEW の値を変更すると、書き込まれる内容が変わります。

イベントごとの複数トリガー

MySQL は、同じテーブルとイベントに対する複数のトリガーをサポートします。FOLLOWS と PRECEDES キーワードが実行順序を制御します。
FOLLOWS/PRECEDES がない場合、MySQL は作成時刻に基づいて実行順序を割り当てます。

トリガーでのエラーの送出

操作を中止して呼び出し元にエラーを返すには、SIGNAL を使います。
BEFORE トリガーがエラーをシグナルすると、挿入/更新/削除は中止され、何も書き込まれません。

トリガーの制限

MySQL のトリガーには、知っておくべきいくつかの制限があります。
  • トリガーは、結果セットを返すストアドプロシージャを呼び出せません
  • トリガーは COMMIT、ROLLBACK、SAVEPOINT を直接使えません(周囲のトランザクションに参加します)
  • トリガーは、自分が定義されているテーブルを参照できません(ほとんどのコンテキストで、同じテーブルへの直接クエリによる再帰的なトリガー呼び出しはできません)
  • AFTER トリガーは NEW の値を変更できません — 行はすでに書き込まれています
  • MySQL はステートメントレベルのトリガーをサポートしません(すべてのトリガーは FOR EACH ROW です)

トリガーを使うべき場面

トリガーは次の用途に適しています。
  • 監査ログ — アプリケーションに関係なく、誰が何をいつ変更したかを記録する
  • CHECK 制約では表現できない複雑な制約の強制
  • 派生データの同期(非正規化された集計列、監査タイムスタンプ)
次の場合はトリガーを避けてください。
  • ロジックが複雑で、デバッグに隠れた副作用の追跡が必要になる場合
  • パフォーマンスが重要な場合 — すべてのトリガーは、影響を受けるすべてのステートメントで行ごとに起動します
  • トリガーがデータを変更し、その存在を知らないアプリケーション開発者を驚かせる場合
隠れたトリガーは、「なぜこの行が変わったのか?」という混乱のよくある原因です。トリガーが存在するなら、データベースの中だけでなく、アプリケーションレベルで目立つように文書化してください。

よくある質問

LOAD DATA INFILE の実行中にトリガーは起動しますか?

はい。INSERT トリガーは、LOAD DATA INFILE でロードされる各行に対して起動します。トリガーが大きな作業を行う場合、LOAD DATA による一括ロードは、まずステージングテーブルにロードしてから INSERT…SELECT でコピーするよりもはるかに遅くなります(INSERT…SELECT もトリガーを起動しますが、SET @disable_trigger = TRUE とトリガー内の条件チェックで一時的に無効化できます)。

トリガーからストアドプロシージャを呼び出せますか?

はい。ただし 1 つ例外があります。呼び出されるプロシージャは結果セット(INTO のない SELECT)を返せません。返すと、MySQL はエラーを返します。トリガーから呼び出されるプロシージャは、OUT パラメータと SELECT...INTO を使えます。

REPLACE INTO でトリガーは起動しますか?

REPLACE は、競合があるときに DELETE + INSERT として実行されます。競合時には、対象テーブルで 4 つすべてが次の順序で起動します。BEFORE INSERT(重複キーのチェック)、次に競合する行に対する BEFORE DELETE と AFTER DELETE、最後に AFTER INSERT です。この削除は本物の行削除なので、参照元テーブルの ON DELETE CASCADE ルールも起動します。

トラブルシューティング

関連項目