ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|
トリガーとは
トリガー (Trigger) はデータベース内に保存されるプロシージャの一種で、特定のテーブルに対して INSERT / UPDATE / DELETE が実行されたときに自動的に呼び出される仕組みです。アプリケーション側で明示的に呼ばなくても DBMS が裏で発火させるため、データ更新を「フック」するために使われます。
主な用途
| 用途 | 例 |
|---|---|
| 監査ログ | UPDATE のたびに変更前後の値を audit テーブルに残す |
| 整合性チェック | 業務ルールに反する値を弾く / 補正する |
| 自動採番・タイムスタンプ | INSERT 時に created_at を自動セット |
| 集計テーブル同期 | 明細テーブルの変更を集計表に反映 |
| 非正規化テーブルの維持 | JOIN 高速化用のサマリ列を更新 |
発火タイミング・対象
| 分類 | 意味 |
|---|---|
| BEFORE | 変更が確定する前に実行。値の補正や事前検証に |
| AFTER | 変更が確定した後に実行。監査ログや別表更新に |
| INSTEAD OF | 主にビューに対し、本来の更新の代わりに実行 |
| FOR EACH ROW | 影響を受けた行ごとに発火 |
| FOR EACH STATEMENT | SQL 文 1 回ごとに発火 (行数に依存しない) |
Oracle のトリガー
-- 監査ログを残すトリガー
CREATE OR REPLACE TRIGGER trg_emp_audit
AFTER UPDATE ON employees
FOR EACH ROW
BEGIN
INSERT INTO emp_audit (emp_id, old_salary, new_salary, changed_at)
VALUES (:OLD.emp_id, :OLD.salary, :NEW.salary, SYSTIMESTAMP);
END;
/
-- BEFORE で自動採番 (シーケンス + トリガー)
CREATE OR REPLACE TRIGGER trg_emp_id
BEFORE INSERT ON employees
FOR EACH ROW
BEGIN
IF :NEW.emp_id IS NULL THEN
SELECT emp_seq.NEXTVAL INTO :NEW.emp_id FROM dual;
END IF;
END;
/
PostgreSQL のトリガー
PostgreSQL ではトリガーから関数 (PL/pgSQL) を呼ぶ二段構えです。
-- 1. トリガー関数を定義
CREATE OR REPLACE FUNCTION fn_emp_audit() RETURNS trigger AS $$
BEGIN
INSERT INTO emp_audit (emp_id, old_salary, new_salary, changed_at)
VALUES (OLD.emp_id, OLD.salary, NEW.salary, now());
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- 2. トリガーをテーブルに紐付け
CREATE TRIGGER trg_emp_audit
AFTER UPDATE ON employees
FOR EACH ROW
EXECUTE FUNCTION fn_emp_audit();
MySQL のトリガー
DELIMITER //
CREATE TRIGGER trg_emp_audit
AFTER UPDATE ON employees
FOR EACH ROW
BEGIN
INSERT INTO emp_audit (emp_id, old_salary, new_salary, changed_at)
VALUES (OLD.emp_id, OLD.salary, NEW.salary, NOW());
END//
DELIMITER ;
OLD / NEW の使い方
| 操作 | OLD | NEW |
|---|---|---|
| INSERT | 使用不可 | 挿入される行 |
| UPDATE | 更新前の行 | 更新後の行 |
| DELETE | 削除される行 | 使用不可 |
削除と確認
-- Oracle
DROP TRIGGER trg_emp_audit;
SELECT trigger_name, status FROM user_triggers;
-- PostgreSQL
DROP TRIGGER trg_emp_audit ON employees;
SELECT tgname, tgenabled FROM pg_trigger WHERE NOT tgisinternal;
-- MySQL
DROP TRIGGER trg_emp_audit;
SHOW TRIGGERS;
トリガー利用の注意点
- 挙動が暗黙的になるためアプリ開発者から「なぜか値が変わる」と見える
- BEFORE トリガーで例外を投げると元の DML がロールバックされる
- 同じテーブルを更新するトリガーは無限ループのリスク
- 大量行を 1 文で更新する場合、行トリガーは性能ボトルネックになりがち
- 監査要件ならトリガー、業務ロジックならアプリ層または CDC が望ましい場面が多い
FAQ
Q: トリガーを使うべき / 避けるべき?
A: 「他に手段がない監査・整合性」ならトリガー。業務ロジックや集計ならアプリ層 / バッチ / マテリアライズド・ビュー / CDC の方が保守しやすいことが多い。
Q: ストアドプロシージャとの違い
A: プロシージャは明示的に呼び出す、トリガーはイベントで自動起動。発火条件があるのが本質的な違いです。
Q: トリガーを一時的に止めたい
A: Oracle ALTER TRIGGER ... DISABLE / PostgreSQL ALTER TABLE ... DISABLE TRIGGER ... / MySQL は DROP 必須。
Q: トリガーの中で同じテーブルを更新したい
A: Oracle では mutating table エラーが出る古典的な問題があります。複合トリガーを使うか、設計を見直して別テーブル更新にするのが定石。PostgreSQL/MySQL では制限がゆるい一方、無限ループに注意。
Q: パフォーマンスの目安
A: 行トリガーは1 行ごとのオーバーヘッドが無視できないため、数万行の一括 UPDATE には致命的になることも。バルク処理が多いなら文トリガー + 自前ロジックで一括処理した方が圧倒的に速いです。
Q: アプリと DB のどちらにロジックを置く?
A: 近年の傾向はアプリ層に寄せるです。理由は: 1) コードが Git で管理できる、2) テストしやすい、3) 横展開しやすい (Read レプリカ・CDC との相性)。監査・整合性などインフラに近い役割だけ DB に残すのが落としどころ。
まとめ
トリガーはうまく使えば強力な整合性ツールですが、設計を誤ると挙動の見えない地雷と化します。「アプリから見えない処理が走るか」「バルク更新で性能を出せるか」を常に天秤にかけ、必要最小限の場所にだけ使うのが鉄則です。代替案として CDC (Debezium) / マテリアライズドビュー / アプリ層イベントなども検討しましょう。
関連
- ストアドプロシージャ — 明示呼び出しの DB ロジック
- ビュー — INSTEAD OF トリガーの主な対象
- 制約 — CHECK / FK で実現できる整合性は制約を優先
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページはありません
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- 【django】ログイン 認証機能 2026-09-08 03:22:09
- MySQL ERROR 1063 Incorrect column specifier for column|原因と直し方 2026-09-08 03:11:09
- 【PHPエラー】Object of class stdClass could not be converted to string 2026-09-07 07:46:04
- Julia Genie ローカル開発サーバ起動完全ガイド 2026-09-07 07:46:04
- Wi-Fi とは|規格と世代(Wi-Fi 4〜7)・周波数帯・CSMA/CA・WPA3 NEW 2026-09-07 07:45:13
- set コマンドでシェルオプションと位置パラメータを操作 | bash 2026-09-07 07:45:13
- JPEG(.jpg/.jpeg)画像形式の完全ガイド — 仕様・マジックナンバー・他形式との比較・EXIF 2026-09-07 07:45:13
- UE5 Get Overlapping Actorsで特定クラスだけ処理|Class Filter・Cast To 2026-09-07 07:45:13
- Linuxで特定拡張子のファイルを再帰削除|find -deleteの安全手順 2026-09-07 07:45:13
- Django CBVでテンプレートに値を渡す|get_context_data・extra_context 2026-09-07 07:45:13
- Linuxで複数ファイルの文字列を一括置換|find・sed・xargsの安全手順 2026-09-07 07:45:13
- Laravelルートグループ|prefix・middleware・nameで一括管理 2026-09-07 07:45:13
- Linux whichコマンドの使い方|絶対パス取得とtype・command -vの違い 2026-09-07 07:45:13
- Linux catコマンドの使い方|行番号表示・複数ファイル連結 2026-09-07 07:45:13
- unable to execute 'gcc': No such file or directory 2026-09-07 07:45:13
コメントを削除してもよろしいでしょうか?