このセクションで、MySQL 5.1 の中でトリガを使用する方法並びにこれらの使用に対する幾つかの制限について説明します。トリガに対する制約に関する追加情報を、 項D.1. 「ストアド ルーチンとトリガの規制」 に掲載します。
トリガは名称を持つ、テーブルに付属するデータベース オブジェクトで、テーブルに対して特定イベントが発生すると有効化されます。幾つかは、トリガに対して、テーブルに挿入すべき値を対象にチェックを実施するか、更新に含まれる値に関して、計算を実行するのに使用されます。
INSERT
ステートメント、DELETE
ステートメントもしくは UPDATE
ステートメントがテーブルに対して実行されると、トリガがテーブルに関連付けられ、定義されて有効化されます。トリガはそのステートメントの前か後にセットして有効化する事ができます。例えば、トリガを、各行をテーブルから削除する前または各行を更新した後に有効化させる事ができます。
CREATE TRIGGER
ステートメントまたは
DROP TRIGGER
ステートメントを使ってトリガを生成させるか除去してください。これらのステートメントに対する構文は、項18.1. 「CREATE TRIGGER
構文」
および 項18.2. 「DROP TRIGGER
構文」
で説明されています。
INSERT
ステートメントの為のテーブルをトリガに関連付けた例がここにあります。それはそのテーブルのカラムの1つに挿入された値を合計する加算器の役を果たします。
以下のステートメントによって、テーブルとそれに対するトリガが生成されます:
mysql>CREATE TABLE account (acct_num INT, amount DECIMAL(10,2));
mysql>CREATE TRIGGER ins_sum BEFORE INSERT ON account
->FOR EACH ROW SET @sum = @sum + NEW.amount;
CREATE TRIGGER
ステートメントは、account
と関連している ins_sum
なる名称のトリガを生成させます。それには、トリガに対する有効化の時期、トリガ
イベント並びにトリガの有効化に要するその他を規定する条項も含まれています。
キーワード BEFORE
はトリガ
アクションの時期を示します。この場合、トリガを各行がテーブルに挿入される前に有効化すべきです。ここで許容されるその他のキーワードは
AFTER
です。
キーワード INSERT
はトリガを有効化するイベントを示します。例では、INSERT
ステートメントによってトリガの有効化が引き起こされます。DELETE
ステートメントおよび UPDATE
ステートメントに対してトリガを生成させる事ができます。
FOR EACH ROW
の後に連なるステートメントは、トリガを有効化するたびに実行すべきステートメントを規定します。これは、トリガに対するステートメントによって影響を被る各行毎に一回発生します。この例では、トリガ
ステートメントは、amount
欄に挿入された値を集計する簡単な
SET
です。そのステートメントは、「新しい行に挿入される
amount
カラムの値」
を意味する NEW.amount
として参照されます。
トリガを利用する為には、
加算器変数をゼロにセットし、INSERT
ステートメントを実行し、その後変数がどんな値になったかを調べます:
mysql>SET @sum = 0;
mysql>INSERT INTO account VALUES(137,14.98),(141,1937.50),(97,-100.00);
mysql>SELECT @sum AS 'Total amount inserted';
+-----------------------+ | Total amount inserted | +-----------------------+ | 1852.48 | +-----------------------+
この場合、INSERT
ステートメントが実行された後の
@sum
の値は 14.98 + 1937.50 -
100
あるいは 1852.48
です。
トリガを破壊する為には、DROP
TRIGGER
ステートメントを利用してください。そのトリガが初期設定スキーマに含まれていない場合には、スキーマ名を規定しなければなりません。
mysql> DROP TRIGGER test.ins_sum;
スキーマの名称欄にトリガ名が存在していますが、これは全てのトリガはスキーマの中に固有の名称を持っていなければならない事を意味します。異なるスキーマの中にあるトリガには同じ名称を付ける事ができます。
スキーマ毎にトリガ名を固有な物としなければいけないという要件に加え、生成させる事ができるトリガのタイプに他の制限があります。特に、有効化の時期と有効化イベントが同じ1つのテーブルに対して、2個のトリガを持つ事はできません。例えば、1つのテーブルに対して、2つの
BEFORE INSERT
トリガもしくは2つの
AFTER UPDATE
トリガを定義する事はできません。
(このセクションの後の部分に述べる) BEGIN
... END
合成ステートメントの構築を
FOR EACH ROW
の後に使う事によって、複数のステートメントを実行するトリガを定義する事ができるので、これを重要な制限とみなすべきではありません。
OLD
なるキーワードと
NEW
なるキーワードを使用すると、トリガによって影響を被る行中のカラムにアクセスする事が可能となります。
(OLD
と NEW
は大文字でも小文字でも入力する事ができます。)INSERT
トリガの場合、NEW.
だけが使用可能です。古い行は存在しません。col_name
DELETE
トリガの場合、OLD.
だけが使用可能です。新しい行は存在しません。col_name
UPDATE
トリガの場合、OLD.
を使って更新前の行のカラムを、また
col_name
NEW.
を使用して、アップデート後の行のカラムをそれぞれ参照する事ができます。
col_name
OLD
の名称を持つカラムは読み取り専用です。(SELECT
権限をお持ちである場合)、それを調べる事ができますが、改訂する事はできません。SELECT
権限をお持ちの場合、NEW
の名称を持つカラムを調べる事ができます。BEFORE
トリガでは、UPDATE
権限をお持ちの場合、SET
NEW.
を使ってその値を変更する事ができます。これは、トリガを使って、新しい行に挿入される、または行を更新する為に利用される値を変更する事ができるという事を意味します。
col_name
=
value
BEFORE
トリガでは、AUTO_INCREMENT
カラムに対する NEW
値は、新しい記録が実際に挿入される時に自動的に生成されるシーケンス番号ではなく、0となります。
OLD
と NEW
はトリガに対する MySQL 拡張子です。
BEGIN ... END
構築を使用する事によって、複数のステートメントを実行するトリガを定義する事ができます。BEGIN
ブロックの中で、条件文やループのようなストアド
ルーチンの中で許容されているその他の構文を使用する事もできます。しかし、ストアド
ルーチンだけに対して、複数のステートメントを実行する1個のトリガを定義する
mysql プログラムを使用した場合、
mysql ステートメント
デリミタを再定義して、トリガの定義の中で
;
ステートメント
デリミタを使用可能にする必要があります。
次の例はこれらの点を例示しています。それは、各行を更新するのに使用すべき新しい値をチェックする
UPDATE
トリガを定義し、その値を0から100までの範囲に収まるように変更します。その値は、行を更新するのに使用する前にチェックする必要があるので、BEFORE
トリガでなければなりません。
mysql>delimiter //
mysql>CREATE TRIGGER upd_check BEFORE UPDATE ON account
->FOR EACH ROW
->BEGIN
->IF NEW.amount < 0 THEN
->SET NEW.amount = 0;
->ELSEIF NEW.amount > 100 THEN
->SET NEW.amount = 100;
->END IF;
->END;//
mysql>delimiter ;
ストアド
プロシージャを別々に定義して、次に単純な
CALL
ステートメントを使ってそれを呼び出して、簡素化する事ができます。これは、幾つかのトリガから同じルーチンを呼び出したい場合にも有益です。
有効化する時トリガが実行するステートメントに記載する事ができる物に対して、幾つかの制限があります。
トリガは、データをクライアントに戻すかダイナミック
SQL を使用する、ストアド
プロシージャを呼び出す CALL
ステートメントを使用する事ができません。(ストアド
プロシージャは、OUT
または
INOUT
パラメータを通してトリガにデータを返す事を許します。)
トリガは、START
TRANSACTION
、COMMIT
や
ROLLBACK
のようなトランザクションを明示的にもしくは暗黙に開始または終了させるステートメントを使用する事ができません。
MySQL はトリガを実行している最中に発生したエラーを以下の通りに処理します:
BEFORE
トリガの機能が停止した場合、対応する行の操作が実施されなくなる。
BEFORE
トリガが、行を挿入するか改訂する
attempt
によって、当該試みがその後成功するか否かに関係なく有効化される。
AFTER
トリガが、BEFORE
トリガ(存在している場合)
並びに行操作が両方共うまく実行された場合に限り実行される。
BEFORE
トリガあるいは
AFTER
トリガを実行している最中に発生したエラーが、トリガに狂いを引き起こし、これによって、全ステートメントを機能停止にする。
トランザクション テーブルに対するステートメントの機能停止は、そのステートメントによって実施された一切の変更のロールバックを引き起こすべきです。トリガの機能停止は、ステートメントに機能停止をもたらし、これによって、トリガの機能停止がロールバックを引き起こす。非トランザクション テーブルに対してこのようなロールバックを行う事ができないので、ステートメントが機能停止しても、エラーが発生した時点より前に実施された一切の変更は有効なまま維持されます。