概要: このチュートリアルでは、SQLトリガーの概念と、データベースシステムで簡単なトリガーを開発する方法について学びます。
SQLトリガーの概要
トリガーとは、データベース内のテーブルで発生した特定のイベントに応答して自動的に実行されるコードの一部です。
トリガーは常に特定のテーブルに関連付けられています。 テーブルが削除されると、関連付けられているすべてのトリガーも自動的に削除されます。
トリガーは、以下のイベントの前または後に呼び出されます。
INSERT
、UPDATE
、またはDELETE
ステートメントを発行すると、関係データベース管理システム(RDBMS)が対応するトリガーを発動します。
一部のRDBMSでは、トリガーはINSERT
、UPDATE
、またはDELETE
ステートメントを呼び出すステートメントの実行結果としても呼び出されます。たとえば、MySQLにはLOAD DATA INFILEがあり、テキストファイルから行を読み取り、非常に高速でテーブルに挿入し、BEFORE INSERT
およびAFTER INSERT
トリガーを呼び出します。
一方、ステートメントはテーブル内の行を削除しても、関連するトリガーを呼び出さない場合があります。たとえば、TRUNCATE TABLEステートメントはテーブル内のすべての行を削除しますが、BEFORE DELETE
およびAFTER DELETE
トリガーを呼び出しません。
トリガー作成ステートメントの構文
トリガーを作成するには、次のステートメントを使用します。
CREATE TRIGGER trigger_name [BEFORE|AFTER] event
ON table_name trigger_type
BEGIN
-- trigger_logic
END;
Code language: SQL (Structured Query Language) (sql)
構文について詳しく見ていきましょう。
- 最初に、
CREATE TRIGGER
句の後にトリガーの名前を指定します。 - 次に、
BEFORE
またはAFTER
キーワードを使用して、特定のイベント(INSERT
、UPDATE
、またはDELETE
など)に応答してトリガーがいつ発生するかを決定します。 - 次に、トリガーがバインドされるテーブルの名前を指定します。
- 次に、
FOR EACH ROW
またはFOR EACH STATEMENT
のいずれかを使用して、トリガーのタイプを指定します。これについては、次のセクションで詳しく説明します。 - 最後に、トリガーのロジックを
BEGIN ... END
ブロックに入れます。
BEGIN END
ブロックのコードを使用するだけでなく、次のようにストアドプロシージャを実行することもできます。
CREATE TRIGGER trigger_name
[BEFORE|AFTER] event
ON table_name trigger_type
EXECUTE stored_procedure_name;
Code language: SQL (Structured Query Language) (sql)
行レベルトリガーとステートメントレベルトリガー
トリガーには、行レベルトリガーとステートメントレベルトリガーの2種類があります。
行レベルトリガーは、UPDATE
ステートメントによって行が影響を受けるたびに実行されます。UPDATE
ステートメントが10行に影響を与える場合、行レベルトリガーは10回実行されます(行ごとに1回)。UPDATE
ステートメントがどの行にも影響を与えない場合、行レベルトリガーはまったく実行されません。
行レベルトリガーとは異なり、ステートメントレベルトリガーは、UPDATE
ステートメントによって影響を受ける行数に関係なく、1回だけ呼び出されます。UPDATE
ステートメントがどの行にも影響を与えなかった場合でも、トリガーは実行されることに注意してください。
トリガーを作成するときは、FOR EACH ROW
またはFOR EACH STATEMENT
をそれぞれ使用して、トリガーが行レベルかステートメントレベルかを指定できます。
SQLトリガーの使用法
通常、トリガーは次のシナリオで使用します。
- テーブルの変更をログに記録します。一部のテーブルには、顧客のメールや従業員の給与など、すべての変更をログに記録したい機密データが含まれています。この場合、
UPDATE
トリガーを作成して、変更を別のテーブルに挿入できます。 - データの複雑な整合性を強制します。このシナリオでは、トリガーを定義してデータを検証し、必要に応じてデータを再フォーマットできます。たとえば、
BEFORE INSERT
またはBEFORE UPDATE
トリガーを使用して、挿入または更新前にデータを変換できます。
SQLトリガーの例
デモンストレーションには、サンプルデータベースのemployees
テーブルを使用します。

salary
列の値の変更をログに記録したいとします。これを行うには、変更を保存するための別のテーブルを作成し、トリガーを使用して変更をこのテーブルに挿入します。
次のステートメントは、salary_changes
テーブルを作成します。
CREATE TABLE salary_changes (
employee_id INT,
changed_at DATETIME DEFAULT CURRENT_TIMESTAMP,
old_salary DECIMAL(8 , 2 ),
new_salary DECIMAL(8 , 2 ),
PRIMARY KEY (employee_id , changed_at)
);
Code language: SQL (Structured Query Language) (sql)
salary_changes
テーブルは、従業員ID、古い給与、新しい給与、および変更時刻を記録します。change_at
列は、変更が発生した時刻を記録するために、デフォルトとして現在の時刻を使用することに注意してください。
次のbefore_update_salary
トリガーは、給与の変更をsalary_changes
テーブルに記録します。
CREATE TRIGGER before_update_salary
BEFORE UPDATE ON employees
FOR EACH ROW
BEGIN
IF NEW.salary <> OLD.salary THEN
INSERT INTO salary_changes(employee_id,old_salary,new_salary)
VALUES(NEW.employee_id,OLD.salary,NEW.salary);
END IF;
END;
Code language: SQL (Structured Query Language) (sql)
トリガーの本体では、新しい給与が古い給与と異なる場合に、変更を挿入します。
トリガー本体内では、OLD
およびNEW
キーワードを使用して、トリガーの影響を受ける行の列にアクセスすることに注意してください。
IDが102の従業員の給与を5%引き上げて、トリガーをテストしましょう。
最初に、従業員102の現在の給与を確認します。
SELECT
employee_id,
first_name,
last_name,
salary
FROM
employees
WHERE
employee_id = 110;
Code language: SQL (Structured Query Language) (sql)

次に、次のUPDATE
ステートメントを発行して、給与を5%引き上げます。
UPDATE employees
SET
salary = salary * 1.05
WHERE
employee_id = 110;
Code language: SQL (Structured Query Language) (sql)

第三に、salary_changes
テーブルを調べて、トリガーが呼び出されたかどうかを確認します。
SELECT
*
FROM
salary_changes;
Code language: SQL (Structured Query Language) (sql)

ご覧のとおり、salary_changes
テーブルには新しいエントリがあります。これは、トリガーが正しく呼び出されたことを意味します。
トリガーの変更
トリガーの定義を変更するには、CREATE OR REPLACE TRIGGER
ステートメントを使用します。
基本的に、CREATE OR REPLACE TRIGGER
は、存在しない場合は新しいトリガーを作成し、存在する場合はトリガーを変更します。
CREATE OR REPLACE TRIGGER
ステートメントは、次のようにCREATE TRIGGER
ステートメントに似ています。
CREATE OR REPLACE TRIGGER trigger_name
[BEFORE|AFTER] event
ON table_name trigger_type
BEGIN
-- trigger_logic
END;
Code language: SQL (Structured Query Language) (sql)
トリガーの削除
トリガーを削除するには、次のようにDROP TRIGGER
ステートメントを使用します。
DROP TRIGGER [IF EXISTS] trigger_name;
Code language: SQL (Structured Query Language) (sql)
IF EXISTS
オプションを使用すると、トリガーが存在する場合にトリガーを削除できます。トリガーが存在しない場合、ステートメントは何も行いません。ただし、IF EXISTS
オプションがない場合、データベースシステムは、存在しないトリガーを削除しようとするとエラーを発行する可能性があります。
また、テーブルを削除すると、テーブルに関連付けられているすべてのトリガーも削除されます。次のステートメントは、before_update_salary
トリガーを削除します。
DROP TRIGGER IF EXISTS before_update_salary;
Code language: SQL (Structured Query Language) (sql)
これで、SQLトリガーを十分に理解し、データベースシステムでトリガーを作成する方法がわかったはずです。