CREATE TRIGGER prevent_negative_salary
BEFORE INSERT ON employees
FOR EACH ROW
BEGIN
IF NEW.salary < 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '給与は負の値にはできません';
END IF;
END;
✅ このトリガーの動作
負の値が入力されるのを防ぐ(エラーハンドリング)
2. AFTER INSERT トリガーを使用し、ログを記録する
CREATE TRIGGER log_new_user
AFTER INSERT ON users
FOR EACH ROW
BEGIN
INSERT INTO user_logs (user_id, action, timestamp)
VALUES (NEW.id, '登録', NOW());
END;
MySQL 5.0.2 以降 でトリガーが利用可能です。
バージョンを確認するには、以下のSQLを実行してください。
SELECT VERSION();
基本的な CREATE TRIGGER 構文
MySQLでトリガーを作成するには、CREATE TRIGGER 文を使用します。
構文
CREATE TRIGGER トリガー名
{BEFORE | AFTER} {INSERT | UPDATE | DELETE}
ON テーブル名
FOR EACH ROW
BEGIN
-- 実行する処理(SQL)
END;
{BEFORE | AFTER} → トリガーの実行タイミング
{INSERT | UPDATE | DELETE} → どのイベントで実行するか
ON テーブル名 → トリガーを適用するテーブル
FOR EACH ROW → 行レベルトリガー(MySQLでは必須)
トリガー作成の実践例
1. BEFORE INSERT トリガー(不正データの防止)
CREATE TRIGGER prevent_negative_salary
BEFORE INSERT ON employees
FOR EACH ROW
BEGIN
IF NEW.salary < 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '給与は負の値にはできません';
END IF;
END;
✅ このトリガーの動作
salary カラムに負の値が入力されると、エラーを発生させて登録を防ぐ。
2. AFTER INSERT トリガー(ログの自動記録)
CREATE TRIGGER log_new_user
AFTER INSERT ON users
FOR EACH ROW
BEGIN
INSERT INTO user_logs (user_id, action, timestamp)
VALUES (NEW.id, '登録', NOW());
END;
CREATE TRIGGER track_salary_changes
AFTER UPDATE ON employees
FOR EACH ROW
BEGIN
INSERT INTO salary_history (employee_id, old_salary, new_salary, changed_at)
VALUES (OLD.id, OLD.salary, NEW.salary, NOW());
END;
CREATE TRIGGER sync_orders
AFTER INSERT ON orders
FOR EACH ROW
BEGIN
INSERT INTO order_backup (order_id, user_id, total_price, created_at)
VALUES (NEW.id, NEW.user_id, NEW.total, NOW());
END;
CREATE TRIGGER prevent_negative_stock
BEFORE INSERT ON inventory
FOR EACH ROW
BEGIN
IF NEW.stock < 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '在庫数がマイナスです。正しい値を入力してください。';
END IF;
END;
CREATE TRIGGER log_user_activity
AFTER INSERT ON users
FOR EACH ROW
BEGIN
INSERT INTO user_logs (user_id, action, timestamp)
VALUES (NEW.id, '登録', NOW());
END;
CREATE TRIGGER track_salary_changes
AFTER UPDATE ON employees
FOR EACH ROW
BEGIN
INSERT INTO salary_history (employee_id, old_salary, new_salary, changed_at)
VALUES (OLD.id, OLD.salary, NEW.salary, NOW());
END;
CREATE TRIGGER update_stock
AFTER UPDATE ON orders
FOR EACH ROW
BEGIN
UPDATE inventory SET stock = stock - NEW.quantity WHERE product_id = NEW.product_id;
END;
CREATE TABLE trigger_logs (
id INT AUTO_INCREMENT PRIMARY KEY,
event_type VARCHAR(50),
message TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
トリガー内で INSERT を使い、処理の流れを記録
CREATE TRIGGER debug_trigger
AFTER INSERT ON users
FOR EACH ROW
BEGIN
INSERT INTO trigger_logs (event_type, message)
VALUES ('INSERT', CONCAT('New user added: ', NEW.username));
END;
✅ この方法を使うと、トリガーの実行結果を確認できる → SELECT * FROM trigger_logs; を実行すると、ログが確認可能。
例えば、以下の2つの AFTER INSERT トリガーを users テーブルに設定しようとするとエラーになる。
CREATE TRIGGER trigger1 AFTER INSERT ON users FOR EACH ROW BEGIN ... END;
CREATE TRIGGER trigger2 AFTER INSERT ON users FOR EACH ROW BEGIN ... END;
MySQLは1つの AFTER INSERT トリガーしか許可しない。
✅ 解決策:
トリガーを1つにまとめて、条件分岐(IF)で複数の処理を実装する
CREATE TRIGGER manage_user_insert
AFTER INSERT ON users
FOR EACH ROW
BEGIN
-- ログを記録
INSERT INTO user_logs (user_id, action, timestamp)
VALUES (NEW.id, '登録', NOW());
-- 初回ログインボーナスを付与
IF NEW.is_new = 1 THEN
INSERT INTO bonuses (user_id, amount) VALUES (NEW.id, 1000);
END IF;
END;
Q3. MySQLのトリガーをデバッグする方法は?
A. トリガーは通常のSQLのように SELECT で結果を確認できないため、デバッグが難しいです。
ログテーブルを活用してデバッグするのが一般的な方法です。 ✅ デバッグ用のログテーブルを作成
CREATE TABLE trigger_logs (
id INT AUTO_INCREMENT PRIMARY KEY,
message TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
✅ トリガーの中で INSERT を使ってログを記録
CREATE TRIGGER debug_trigger
AFTER INSERT ON users
FOR EACH ROW
BEGIN
INSERT INTO trigger_logs (message)
VALUES (CONCAT('New user added: ', NEW.username));
END;
CREATE TRIGGER log_new_user
AFTER INSERT ON users
FOR EACH ROW
BEGIN
INSERT INTO user_logs (user_id, action, timestamp)
VALUES (NEW.id, '登録', NOW());
END;
SHOW TRIGGERS で作成したトリガーを確認し、DROP TRIGGER で削除が可能
3. トリガーの活用事例
データの自動同期(バックアップ)
orders テーブルのデータを order_backup に自動保存
データの自動検証
BEFORE INSERT を使い、負の値の入力を防止
ログ管理
AFTER INSERT でユーザーアクティビティを user_logs に記録
通知・外部システム連携
AFTER UPDATE でストアドプロシージャを呼び出し、メール通知を実装
変更履歴の保存
AFTER UPDATE で salary_history に変更前後のデータを記録
4. トリガー使用時の注意点
パフォーマンスへの影響
トリガーが多すぎるとデータ操作の処理速度が低下
ネストしたトリガー(トリガー内で別のトリガーが発火)に注意
デッドロックのリスク
BEFORE トリガーを活用してロック競合を回避
トリガーの制約
トランザクション制御(COMMIT / ROLLBACK)ができない
1つのテーブルに同じ種類のトリガーを複数設定できない
デバッグ方法
ログテーブルを作成し、トリガーの実行履歴を記録
SHOW TRIGGERS や information_schema.TRIGGERS で設定を確認