「トリガーを設定してください」と言われて、 私の頭の中には鳥のシルエットがぽわ〜んと浮かびました。
「えっ…鳥?どこを飛ぶの? 何を呼び出すの? 急に撃たれるやつ⁉」
──そんなレベルで、PL/SQLのトリガーとは何か?すら分かっていなかった私が、いまこの記事を書いています。
だけど安心してください。
わたしも最初は「勝手に動くってこわい」「何が起きたのか分からない」と思っていました。
でも少しずつ触れていくうちに、トリガーは“うっかり”を守ってくれる静かな優等生だと分かってきたんです。
本記事では、そんな「トリガー?なにそれ?」レベルだった私でも理解できた内容を、初心者目線でやさしく紹介します。
- トリガーって何者?
- どんなときに使うの?
- 実はミス予防の味方⁉
そんな疑問をまるっと解消しつつ、業務の“うっかりミス”を防ぐためのトリガー活用術をお届けします!
その“更新し忘れ”、トリガーで救えます
「このカラム、毎回手動で更新するの面倒だな…」
「更新し忘れて、あとでデータがチグハグになってた…」
そんな経験、ありませんか?
私はよくありました。というか、今でもたまにやらかします(反省はしている)。
バッチ処理の中で「更新日時」をつけ忘れて「あれ、このレコード、いつ更新したんだっけ?」となったり、 明細テーブルだけ更新してヘッダテーブルに反映するのを忘れたり…。
うっかり人間 vs データ整合性の仁義なき戦い──。
でも、そこにそっと登場してくれるのが、 そう、あの「トリガー」さんなのです。
トリガーって、何をしてくれるの?
一言で言うと、ある条件が起きたときに“自動で”処理を発動してくれるPL/SQLの仕組みです。
たとえば…
- レコードがINSERTされたときに、自動でログを書き込む
- UPDATEが走ったら、last_updated_atカラムにタイムスタンプを入れる
- DELETEされたときに、削除前の内容を別テーブルに保存する
こんな処理を、人間が意識して書かなくても“裏側で勝手にやってくれる”のがトリガーのすごいところ。
つまり、こういうことです:
- 「更新処理にログ記録を追加し忘れた…」 → トリガー「私がこっそり書いておきましたよ。」
- 「手で書き込むの忘れた変換結果…」 → トリガー「さっきのUPDATEに合わせて自動で処理しておきました。」
もはや賢くて忠実な秘書。たまにこっそり働いてくれるタイプの。
業務でありがちな“うっかりミス”、実はトリガーで防げるかも
- updated_atを更新し忘れた
- 詳細テーブルにデータを入れたけど、集計情報を親テーブルに反映し忘れた
- 禁止パターンのデータをうっかりINSERTしてしまった
- 変更履歴をログに残し忘れて「あのときどうだったっけ?」が見えなくなった
これ、全部トリガーで防げる or 自動でカバーできるケースなんです。
トリガーって難しそうに聞こえるけど…
たしかに「何かが自動で動く」と聞くと、ちょっとこわいし不安になりますよね。
でも大丈夫。この記事では、トリガーの基本・種類・使い方・注意点を、初心者向けにやさしく紹介していきます!
次章では、そもそも「トリガーってどういう仕組みなの?」という基本から丁寧に解説していきます。
“鳥じゃないトリガー”の正体、ここでじっくり知っていきましょう!
トリガーとは?PL/SQLでできる“自動化”の仕組み
さて、トリガー=鳥問題はさておき、ここからはPL/SQLにおける「トリガーって何?」という話をしていきます。
結論から言えば、トリガーとは
「特定のイベントをきっかけに、自動で処理を実行する仕組み」です。
つまり、人間が「今からこのプロシージャを呼び出すぞ!」と命令しなくても、データベースが勝手に実行してくれる裏方のような存在なんですね。
トリガーが動く“きっかけ”って?
トリガーは何もしないときは静かにしています(いわゆる“待機中”状態)。 でも、ある出来事が起こると…
- レコードが追加された(INSERT)
- 既存のレコードが変更された(UPDATE)
- レコードが削除された(DELETE)
このような「DML操作(データをいじる動き)」が起きた瞬間に、自動で起動するのがトリガーです。
たとえば:
顧客情報が新規登録されたら、トリガーが発動して登録時刻を保存する。
商品価格が変更されたら、古い価格を履歴テーブルに自動保存する。
こうした動きを毎回コードに書かなくても、“指定しておけば勝手に動いてくれる”──これがトリガーの最大の魅力です。
BEFOREトリガー vs AFTERトリガー
PL/SQLのトリガーには、いつ発動するかによって大きく2種類に分かれます:
タイプ | 説明 | よく使う場面例 |
---|---|---|
BEFOREトリガー | DML文が実際に処理される前に発動 | 値の整形や検証、データ補正など |
AFTER トリガー | DML文の処理が終わったあとに発動 | ログ記録、通知、履歴保存など |
「変更前に値を加工したい」ならBEFORE、 「変更が済んでから何かしたい」ならAFTERを使います。
行トリガーと文トリガーの違い
もうひとつの分類が、「何に対して動作するか」です。
種類 | 説明 |
---|---|
行(ROW)トリガー | 対象テーブルの各行ごとに1回ずつ発動 |
文(STATEMENT)トリガー | 対象SQLが1回実行されたタイミングで1回だけ発動 |
たとえば、UPDATE文で10行更新された場合:
- 行トリガーなら10回動きます(1行ごと)
- 文トリガーなら1回だけ動きます(全体で1発)
実は、:NEW と :OLD っていう特別な変数があります
トリガーの中でよく出てくるこの2人、最初は「なんだこの謎のコロンは…」って戸惑うと思いますが、とっても便利。
- :NEW.column_name → 新しくセットされる値(INSERT・UPDATEで使える)
- :OLD.column_name → 変更前の値(UPDATE・DELETEで使える)
つまり、たとえばこういうことができます:
IF :OLD.price <> :NEW.price THEN
INSERT INTO price_log (old_price, new_price)
VALUES (:OLD.price, :NEW.price);
END IF;
「価格が変わったときだけ履歴を残したい」という処理が、すっごく自然に書けますよね!
つまり、トリガーは“自動で条件反射するミニロボット”みたいな存在
「INSERTされたらこれ」「UPDATEされたらあれ」といった条件付きの自動処理を 人間がその都度書かなくても、データベースがきっちり反応してくれる。
それがトリガーです。
次章では、実際に「初めてのトリガーを書いてみよう!」をテーマに、 初心者向けのシンプルな例とその書き方を解説していきます。
はじめてのトリガー ― 基本構文とやさしい例
トリガーの存在は理解できた。 “自動で動く仕組み”って便利そう。
……でも。
「で、どうやって書くの?」 「あの :NEW とか :OLD とか、やっぱり謎」
はい、それです。安心してください、ここから一緒に“人生最初のトリガー”を書いていきましょう!
トリガーの基本構文
PL/SQLでのトリガー定義は、基本的に以下の形をとります:
CREATE [OR REPLACE] TRIGGER トリガー名
タイミング イベント ON テーブル名
[FOR EACH ROW] -- 行トリガーのとき
BEGIN
-- 実行したい処理
END;
/
用語がわからなくても大丈夫!一つずつ紐解きます:
要素 | 意味 |
---|---|
タイミング | BEFORE(処理前) or AFTER(処理後) |
イベント | INSERT、UPDATE、DELETE など |
FOR EACH ROW | 各レコードごとに実行する“行トリガー”の場合に指定 |
本体 | 実行したい処理内容(ログ記録など) |
はじめての例:updated_atを自動更新
「レコードをUPDATEしたとき、自動でupdated_atを現在日時にしてほしい」 ──
そんな、エンジニアなら一度は書いた(そしてたまに忘れた)やつをトリガーで自動化してみます。
CREATE OR REPLACE TRIGGER trg_auto_update_timestamp
BEFORE UPDATE ON users
FOR EACH ROW
BEGIN
:NEW.updated_at := SYSDATE;
END;
/
解説
- BEFORE UPDATE:更新処理が実行される直前に発動
- FOR EACH ROW:usersテーブルの各行ごとに動作
- :NEW.updated_at := SYSDATE;:更新後のupdated_atに現在時刻を代入
これで、UPDATE文にupdated_atの指定を書かなくても、自動で現在時刻が入るようになります!
UPDATE対象の条件を絞ることもできます
IF :OLD.email <> :NEW.email THEN
INSERT INTO email_change_log (user_id, old_email, new_email, changed_at)
VALUES (:NEW.id, :OLD.email, :NEW.email, SYSDATE);
END IF;
このように、“値が変わったときだけ”処理を実行することもできます。
思ってるより自然な感覚で、条件分岐できるんです!
やってみて気づいたこと
初めてトリガーを書いたとき、「あ、PL/SQLってちゃんと“会話”してくれる」と感じた瞬間がありました。
「この値が変わったら、こう動いてね」 「処理の前にちょっとだけ介入したいんだ」 そんな“気持ち”を、ちゃんと受け取ってくれる感じ。
……まぁ、たまに不機嫌で無言のエラーを返してくるんですが(SQL Developerくん、ログ出して…)。
焦らず慣れていけば大丈夫
トリガーには書き方のクセもありますし、:NEW / :OLD のミスでエラーになることもあります。
でも、少しずつ「こう書けば自動でやってくれるんだ」という感覚がつかめてくると、PL/SQLに対しての信頼感と親近感がグッと増してきます。
次章では、実務で「おお、これは便利だった!」と感じたトリガーの実用例をいくつかご紹介します。
きっとあなたの現場でも「これ、ウチでも使えそうかも」が見つかりますよ。
実務で使えるトリガー活用例3選
トリガーの構文にも慣れてきたところで、 いよいよ「うちの職場でも使えるかも?」が見えてくる時間です。
ここでは、私が「これ、地味だけど便利だった…!」と感じた活用例を3つご紹介します。
どれも実際に現場で“うっかり”を防いだ救世主たちです。
活用例①:変更前後の値をログに残す(UPDATE履歴保存)
よくある困りごと:
- 「誰かがデータ変更したっぽいけど、前の値が分からない…」 → デバッグ困難!犯人不明!タイムスタンプだけが味方!
トリガーの使い方:
CREATE OR REPLACE TRIGGER trg_save_price_change
AFTER UPDATE ON products
FOR EACH ROW
WHEN (OLD.price <> NEW.price)
BEGIN
INSERT INTO price_change_log (
product_id, old_price, new_price, changed_at
) VALUES (
:NEW.id, :OLD.price, :NEW.price, SYSDATE
);
END;
/
- UPDATE前後で価格が変わったときだけ発動
- 履歴テーブルに「何が→何に変わったか」を保存
「“その変更、いつ誰が何をやったのか”を残せる」という安心感がすごいです。
活用例②:連動テーブルの値を自動反映する
よくある困りごと:
- 「明細テーブルを更新したら、ヘッダー情報も手動で直す…えっ、それ人間がやるの⁉」
トリガーの使い方:
たとえば、order_items(明細)の合計金額をorders(ヘッダ)に反映する場合:
CREATE OR REPLACE TRIGGER trg_update_order_total
AFTER INSERT OR DELETE OR UPDATE ON order_items
FOR EACH ROW
BEGIN
UPDATE orders
SET total_amount = (
SELECT SUM(price * quantity) FROM order_items
WHERE order_id = :NEW.order_id
)
WHERE id = :NEW.order_id;
END;
/
- 明細の変更に合わせて、ヘッダの合計金額を自動更新
- INSERT/DELETE/UPDATEどれでも反応するように設定
「伝票ズレたまま放置…」みたいな事故を防止できるので、経理にもやさしい✨
活用例③:禁止パターンの登録を防止する
よくある困りごと:
- 「この値は禁止って言ってたじゃん…」 → 入力バリデーション漏れ or 意図的なバイパスが怖い
トリガーの使い方:
CREATE OR REPLACE TRIGGER trg_block_test_email
BEFORE INSERT OR UPDATE ON users
FOR EACH ROW
BEGIN
IF :NEW.email LIKE '%@example.com' THEN
RAISE_APPLICATION_ERROR(-20001, 'テスト用メールアドレスは使用できません');
END IF;
END;
/
- 指定の条件に一致する値がきたら強制的にエラーを返す
- アプリ側で防ぎきれない“裏ルート”をシャットアウト
「大事な制限を“データベースレベル”で守れる」安心感がたまりません。
まとめ:地味だけど、ちゃんと役に立つ
トリガーは派手な機能ではないですが、「あれ、動いてる…!」という瞬間が、じわじわ効く自動化の実感につながります。
- 手動更新を忘れても自動で反映
- 履歴を取ることで安心して変更できる
- 禁止ルールも裏でしっかり守ってくれる
そう、トリガーは“優しすぎる裏方”なんです。
次章では、「そんな便利なトリガーにも実は“落とし穴”がある…」という注意ポイントをお伝えします。
便利だからこそ、使い方は慎重に。その辺のバランス感覚も、PL/SQL道には欠かせません。
トリガーを使うときの注意点と落とし穴
これまで紹介してきたトリガー、確かに便利です。
でもその反面、“思わぬ動きをしてしまうことがある”のも事実。
「INSERTしたら勝手に何かが動いてる」 「UPDATEが止まったと思ったら、トリガーがエラー返してた」 「ループして終わらない…えっ、無限ループ⁉」
──そんな“予想外のオチ”にならないよう、ここではトリガーにまつわる注意ポイントと、落とし穴の回避法を紹介していきます。
注意点①:勝手に動く=制御しづらい
トリガーは“呼び出されないのに勝手に動く”ことが強みであり、怖さでもあります。
- アプリ側の開発者が「そのテーブルにUPDATEしたら、別のテーブルにも勝手に変更入った…え?」となる
- トリガーを知らない人がテーブル操作したら、意図しない副作用が出る
解決法
設計書やDBのドキュメントに、必ずトリガーの一覧と発動条件を明記しておく (USER_TRIGGERSなどの情報ビューを活用!)
注意点②:トリガーが原因でDMLが失敗することもある
たとえば、トリガー内で何かの制限をかけていて、それが満たされないと
ORA-20001: テスト用メールアドレスは使用できません
のように、アプリ側で意図していなかったエラーが出ることも。
解決法
RAISE_APPLICATION_ERRORの使い方に注意し、親切なメッセージを設定する また、トリガーで止める目的と、UI側で防ぐ処理との役割分担も見直すと◎
注意点③:無限ループに注意!
これは“トリガーあるある”ですが…
AテーブルにUPDATE → トリガー発動でBテーブルをUPDATE → そのBテーブルにもトリガーがあって、またAテーブルにUPDATE → …エンドレス地獄。
無限ループでCPUが悲鳴を上げてしまう可能性があります。
解決法
- トリガーが相互に呼び合わないように設計する
- 必要に応じて「値が変わったときのみ発動」の条件をつける 例:WHEN OLD.col <> NEW.col などの条件追加
注意点④:デバッグが地味に大変
トリガーの挙動は「直接呼び出しじゃない」ため、動作確認がやや面倒です。
- 発動条件を満たしてるのに、トリガーが動いてるのかどうかわからない…
- DBMS_OUTPUT.PUT_LINEを入れても出ない(開発環境で出力ONにしていない)
解決法
- トリガー内でもログテーブルに情報を書き出すようにする
- 開発環境では必ずSERVEROUTPUT ONにする/ログビュー確認を徹底する
注意点⑤:チーム運用時は特に“共有”が大事
トリガーは便利だけど、勝手に発動するタイプの“裏処理”。
その存在を知らないと、チーム内で「謎の挙動」に悩まされることも。
解決法
- 設計書にトリガー一覧を書く
- 命名ルール(trg_+テーブル名+目的)などを統一する
- レビューやpull request時に“トリガーあります”宣言を入れる
まとめ:トリガーは便利だけど“慎重な取り扱い”を
トリガーの力 | トリガーの注意点 |
---|---|
自動で処理してくれる | 発動タイミングが読みにくい |
副作用を防げる | 無限ループのリスクがある |
うっかりを補助する | 誤発動・誤反応に注意 |
ちゃんと設計し、ちゃんと記録し、ちゃんと検証する── それさえ守れば、トリガーは業務効率化の強力な味方になってくれます。
次章では、「そんなトリガーを“きちんと動いてるか”確認する方法」についてご紹介します。
いよいよ実践編ですね。誰かのトリガーに振り回されないためにも、スキルアップしていきましょう!
トリガーが“効いてる”か確認する方法
ここまででトリガーの便利さも、その怖さもだいぶ分かってきたところだと思います。
では、いよいよ「今このトリガーって動いてるの?」とか、 「誰がどのトリガー作ったの…?」とか、 そんな“裏方チェック”をしていくフェーズに入りましょう。
方法①:トリガーの定義を確認する(USER_TRIGGERSビュー)
Oracleには、現在ログインしているユーザーが持っているトリガーの一覧が見られるビューが用意されています。
その名も…
SELECT trigger_name, table_name, triggering_event, status
FROM user_triggers;
カラム名 | 意味 |
---|---|
trigger_name | トリガーの名前 |
table_name | どのテーブルに紐づいているか |
triggering_event | INSERT/UPDATEなど、何が起きたら動くか |
status | ENABLEDなら有効。DISABLEDなら無効 |
まずは「どんなトリガーが、どんなテーブルにいるのか」を把握しましょう!
方法②:トリガーのソースコードを見る(DBMS_METADATA.GET_DDL)
そのトリガー、どんな処理をしているのかも気になりますよね。
そんなときは、以下の方法でトリガー定義を取得できます:
SELECT DBMS_METADATA.GET_DDL('TRIGGER', 'trg_update_order_total')
FROM dual;
→ SQL Developerなどで実行すれば、CREATE TRIGGER文の全文が出力されます!
方法③:動作ログや履歴で“効いてる感”を確認する
トリガーは直接画面に出てこないぶん、「痕跡」で見るのがポイント。
例えば…
- トリガー内にINSERT INTO log_table(…)が仕込まれていた場合 → ログテーブルの件数が増えていれば「動いた証拠」
- トリガー内のupdated_at := SYSDATE;が動いているか? → 該当レコードのupdated_atを確認し、意図通りに更新されていればOK
“直接確認できないなら、結果で確認する”──エンジニアの基本ですね!
方法④:開発環境でわざと発動条件を試す
本番ではなかなかできませんが、開発環境では以下のようなテスト的発動をすると◎
-- トリガー発動用のテストINSERT
INSERT INTO users (id, email, name) VALUES (999, 'test@example.com', 'テスト太郎');
→ その結果、トリガーが何か追加処理してくれているか?ログが出るか?履歴が残るか?などをチェック。
明示的に「この操作したら発動するはず!」という確認ができると安心です。
おまけ:トリガーって誰が作ったの?
社内で「このテーブル、なんか知らんけど値が勝手に書き変わるんだけど…」という現象に出会ったこと、ありませんか?
そんなときは、ALL_TRIGGERS や DBA_TRIGGERS を使うことで、他ユーザーが作ったトリガーも確認できます(DB権限があれば)!
SELECT owner, trigger_name, table_name
FROM all_triggers
WHERE table_name = 'users';
「影の仕掛け人」が見つかるかもしれません。
まとめ:ちゃんと“見える化”できれば怖くない
確認ポイント | 方法 |
---|---|
どんなトリガーがあるか | USER_TRIGGERSビューで一覧取得 |
何を処理しているか | DBMS_METADATA.GET_DDLで定義を確認 |
動いてるかどうか | ログ・履歴・カラムの変化でチェック |
他人が作ったか?どのテーブルか? | ALL_TRIGGERSやDBA_TRIGGERSでクロス確認 |
トリガーは“見えない優秀なスタッフ”ですが、その働きを見える化しておけば安心して使えます。
怖がらず、でも油断せず。これがトリガー活用のコツです!
まとめ ― 安心して任せられる“自動処理の相棒”に
ここまで読んでくださってありがとうございます。
トリガーという名の「鳥っぽい存在(?)」が、まさかこんなに便利だったなんて…と、少しでも思っていただけたなら、この記事を書いた甲斐があります。
トリガーは“地味だけど頼れる”存在です
PL/SQLのトリガーは、見えないところで静かに働いてくれる裏方の優秀スタッフ。
使い方を間違えなければ、あなたの業務を確実に、そしてスマートに支えてくれます。
- 手動の更新や履歴管理を、うっかり忘れなくなる
- ログを勝手に残してくれるのでトラブル調査がラクになる
- データの整合性を、こっそり守ってくれる
そう、「勝手にいいことをしてくれる」仕組みなんです。
ただし“勝手に動く”ならではの注意も忘れずに
便利だからこそ、以下のポイントには要注意:
- 発動条件をちゃんと理解してから設計する
- 無限ループの可能性があるなら条件分岐を入れる
- チーム内で存在を共有する&記録する
- 影響範囲をログやビューで“見える化”しておく
→ トリガーを安心して任せるには、ちょっとした配慮が必要なんですね。
はじめは「トリガー?鳥?」でもOKです
私自身も、「トリガーって何?急に出てきた鳥?」というところから始まりました。
でも、トリガーが何をしてくれているのかが少しずつわかってくると、 データベースとの付き合い方が一気に変わってきました。
「処理の自動化って、怖いことじゃないんだ」 「自分が触ってるコードって、ちゃんと守られてるんだ」 そんな安心感が、ほんの少しずつ積み上がってきたんです。
トリガーを“相棒”にするために
これからトリガーを書こうと思っているあなたへ。
- 最初は小さな自動化からでOK
- 必ず条件を意識して、目的を明確に
- そして「どう確認するか」「誰が見るか」を考えて設計する
トリガーは、コードだけじゃなくチームや業務への信頼感まで支えてくれる存在になります。
次につながるヒント
もしトリガーが「ちょっと面白いかも」と思えたら、こんなテーマにもぜひ挑戦してみてください:
- トリガー+ログテーブル連携で“見えるデバッグ”を
- ユーザー定義エラー(RAISE_APPLICATION_ERROR)で“優しい制限”を
- 複数イベント対応トリガーや複数テーブル連携も面白い世界です

トリガーは、見えないところでこっそり働いてくれる“自動処理の相棒”。 最初はちょっとクセ強いですが、じっくり向き合えば業務の味方になってくれます。
もしあなたが今、「トリガーってちょっとこわそう」と思っていたなら── この記事が、ほんの少しでも安心の材料になっていたら幸いです。
そしてこの先、「あ、ここにトリガー使えそうかも」と思える場面が来たら、 そのひらめきはきっと、あなたの成長の証です。
コメント