MySQL トリガーは、ストアド プロシージャと同様、MySQL に埋め込まれたプログラムであり、MySQL でのデータ管理のための強力なツールです。違いは、ストアド プロシージャの実行には CALL ステートメントの使用が必要であるのに対し、トリガーの実行には CALL ステートメントの使用が必要なく、手動で開始する必要もないことです。代わりに、トリガーされてアクティブ化されます。データテーブルに対する関連操作を通じて実行を実現します。たとえば、学生テーブルに対して操作 (INSERT、DELETE、または UPDATE) が実行されるとアクティブ化されます。
トリガーはデータ テーブルと密接に関連しており、主にテーブル内のデータを保護するために使用されます。特に相互に関連する複数のテーブルがある場合、トリガーは異なるテーブル間でデータの一貫性を維持できます。
MySQL では、トリガーは INSERT、UPDATE、および DELETE 操作を実行する場合にのみアクティブ化され、他の SQL ステートメントではトリガーはアクティブ化されません。
では、なぜトリガーを使用するのでしょうか? 例えば、実際にプロジェクトを開発していると、次のような場面に遭遇することがよくあります。
- 学生に関するレコードが学生テーブルに追加されると、学生の総数も変更する必要があります。
- 学生の記録を追加するときは、年齢が範囲要件を満たしているかどうかを確認する必要があります。
- 生徒の情報を削除する場合は、成績表上の該当する記録を削除する必要があります。
- データが削除された場合、バックアップ コピーをデータベース アーカイブ テーブルに保持する必要があります。
上記の状況で実装されるビジネス ロジックは異なりますが、いずれもデータ テーブルが変更されたときに何らかの処理を自動的に実行する必要があります。このとき、トリガー処理を利用することができます。たとえば、最初のケースでは、トリガー オブジェクトを作成し、学生レコードが追加されるたびに学生の総数を計算する操作を実行できます。これにより、学生レコードが追加されるたびに、学生の総数と学生の総数が確実に計算されます。生徒の記録の数が計算され、一貫しています。
トリガーのメリットとデメリット
トリガーの利点は次のとおりです。
- トリガーの実行は自動であり、トリガー関連テーブル内のデータに対応する変更が加えられた直後に実行されます。
- トリガーは、FOREIGN KEY 制約や CHECK 制約よりも複雑なチェックと操作を実装できます。
- トリガーはテーブル データへのカスケード変更を実装し、データの整合性をある程度確保できます。
トリガーの欠点は次のとおりです。
- トリガーを使用して実装されたビジネス ロジックは、特に複数のトリガーが関係する場合に、問題が発生したときに特定するのが難しく、後のメンテナンスが困難になります。
- トリガーを多用すると、コード構造が簡単に破壊され、プログラムが複雑になる可能性があります。
- 変更する必要があるデータの量が多い場合、トリガーの実行効率は非常に低くなります。
MySQL でサポートされるトリガー
実際の使用では、MySQL は INSERT トリガー、UPDATE トリガー、DELETE トリガーの 3 つのトリガーをサポートします。
1) INSERTトリガー
INSERT ステートメントの実行前または後に応答するトリガー。
INSERT トリガーを使用する場合は、次の点に注意する必要があります。
- INSERT トリガー コード内では、NEW (大文字と小文字を区別しない) という名前の仮想テーブルを参照して、挿入された行にアクセスできます。
- BEFORE INSERT トリガーでは、NEW の値も更新できます。これにより、挿入された値を変更できます (対応する操作権限がある限り)。
- AUTO_INCREMENT 列の場合、NEW には INSERT が実行される前は値 0 が含まれ、INSERT が実行された後は自動的に生成された新しい値が含まれます。
2) UPDATEトリガー
UPDATE ステートメントの実行前または後に応答するトリガー。
UPDATE トリガーを使用する場合は、次の点に注意する必要があります。
- UPDATE トリガー コード内では、NEW (大文字と小文字を区別しない) という名前の仮想テーブルを参照して、更新された値にアクセスできます。
- UPDATE トリガー コード内では、OLD という名前の仮想テーブル (大文字と小文字は区別されません) を参照して、UPDATE ステートメントが実行される前の値にアクセスできます。
- BEFORE UPDATE トリガーでは、NEW の値も更新される可能性があり、これにより UPDATE ステートメントで使用される値を変更できます (対応する操作権限がある場合に限ります)。
- OLD の値はすべて読み取り専用であり、更新できません。
注: テーブル自体の更新操作をトリガーするようにトリガーが設計されている場合、使用できるのは BEFORE タイプのトリガーのみであり、AFTER タイプのトリガーは許可されません。
3) DELETEトリガー
DELETE ステートメントの実行前または後に応答するトリガー。
DELETE トリガーを使用する場合は、次の点に注意する必要があります。
- DELETE トリガー コード内では、OLD という名前の仮想テーブル (大文字と小文字は区別されません) を参照して、削除された行にアクセスできます。
- OLD の値はすべて読み取り専用であり、更新できません。
一般に、MySQL はトリガーの使用中に次の方法でエラーを処理します。
トランザクション テーブルの場合、トリガーが失敗し、その結果ステートメント全体が失敗した場合、ステートメントによって実行されたすべての変更がロールバックされます。非トランザクション テーブルの場合、ステートメントが失敗した場合でも、そのようなロールバックは実行できません。以前の変更は引き続き残ります。有効になります。
BEFORE トリガーが失敗した場合、MySQL は対応する行に対して操作を実行しません。
BEFORE または AFTER トリガーの実行中にエラーが発生した場合、トリガーを呼び出すステートメント全体が失敗します。
MySQL は、BEFORE トリガーと行操作の両方が正常に実行された場合にのみ AFTER トリガーを実行します。
MySQL はトリガーを作成します (CREATE TRIGGER)
トリガーは、 MySQLデータ テーブルに関連するデータベース オブジェクトであり 、定義された条件が満たされたときにトリガーされ、トリガーで定義された一連のステートメントを実行します。トリガーのこの機能は、アプリケーションがデータベース側でデータの整合性を確保するのに役立ちます。
MySQLデータベース基礎スキル完全演習https://edu.csdn.net/course/detail/36210
基本的な文法
MySQL 5.7 では、CREATE TRIGGER ステートメントを使用してトリガーを作成できます。
構文形式は次のとおりです。
CREATE <触发器名> < BEFORE | AFTER >
<INSERT | UPDATE | DELETE >
ON <表名> FOR EACH Row<触发器主体>
構文については以下で説明します。
1) トリガー名
トリガーの名前。トリガーには、現在のデータベース内で一意の名前が必要です。特定のデータベースに作成する場合は、名前の前にデータベースの名前を付ける必要があります。
2) 挿入 | 更新 | 消去
トリガー イベント。トリガーをアクティブにするステートメントのタイプを指定するために使用されます。
注: 3 つのトリガーの実行時間は次のとおりです。
- INSERT: 新しい行がテーブルに挿入されるとトリガーがアクティブになります。たとえば、INSERT の BEFORE トリガーは、MySQL の INSERT ステートメントだけでなく、LOAD DATA ステートメントによってもアクティブ化できます。
- DELETE: DELETE ステートメントや REPLACE ステートメントなど、テーブルからデータ行が削除されるときにトリガーがアクティブになります。
- UPDATE: UPDATE ステートメントなど、テーブル内のデータ行が変更されたときにトリガーがアクティブになります。
3) 前 | 後
BEFORE と AFTER (トリガーが起動される瞬間) は、トリガーが起動されるステートメントの前か後に起動されるかを示します。新しいデータが条件を満たしているかどうかを確認する場合は、BEFORE オプションを使用します。トリガーをアクティブにするステートメントの実行後に複数の変更を完了する場合は、通常、AFTER オプションを使用します。
4) テーブル名
トリガーが関連付けられているテーブルの名前。このテーブルは永続テーブルである必要があります。トリガーを一時テーブルまたはビューに関連付けることはできません。テーブル上でトリガー イベントが発生すると、トリガーがアクティブになります。同じテーブルに、同じ起動時間とイベントを持つ 2 つのトリガーを含めることはできません。たとえば、データ テーブルの場合、同時に 2 つの BEFORE UPDATE トリガーを使用することはできませんが、BEFORE UPDATE トリガーと BEFORE INSERT トリガー、または BEFORE UPDATE トリガーと AFTER UPDATE トリガーを使用することはできます。
5) トリガー本体
トリガー アクションの本体には、トリガーがアクティブ化されたときに実行される MySQL ステートメントが含まれています。複数のステートメントを実行する場合は、BEGIN…END 複合ステートメント構造を使用できます。
6) 各行について
一般に、行レベルのトリガーを指します。トリガー イベントの影響を受ける行ごとにトリガー アクションをアクティブ化する必要があります。たとえば、INSERT ステートメントを使用して複数行のデータをテーブルに挿入する場合、トリガーは挿入されたデータの各行に対して対応するトリガー アクションを実行します。
注意:每个表都支持 INSERT、UPDATE 和 DELETE 的 BEFORE 与 AFTER,因此每个表最多支持 6 个触发器。每个表的每个事件每次只允许有一个触发器。单一触发器不能与多个事件或多个表关联。
さらに、MySQL では、データベース内の既存のトリガーを表示する必要がある場合、SHOW TRIGGERS ステートメントを使用できます。
BEFORE タイプのトリガーを作成する
test_db データベースのデータ テーブル tb_emp8 は、id、name、deptId、給与フィールドを含む従業員情報テーブルであり、データ テーブル tb_emp8 のテーブル構造は次のとおりです。
mysql> SELECT * FROM tb_emp8;
Empty set (0.07 sec)
mysql> DESC tb_emp8;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(22) | YES | UNI | NULL | |
| deptId | int(11) | NO | MUL | NULL | |
| salary | float | YES | | 0 | |
+--------+-------------+------+-----+---------+-------+
4 rows in set (0.05 sec)
[例 1] SumOfSalary という名前のトリガーを作成する トリガー条件は、データ テーブル tb_emp8 にデータを挿入する前に、新しく挿入された給与フィールドの値を合計することです。入力SQL文と実行処理は以下のとおりです。
mysql> CREATE TRIGGER SumOfSalary
-> BEFORE INSERT ON tb_emp8
-> FOR EACH ROW
-> SET @sum=@sum+NEW.salary;
Query OK, 0 rows affected (0.35 sec)
トリガー SumOfSalary の作成後、テーブル tb_emp8 にレコードが挿入されると、以下に示すように、定義された合計値が 0 から 1500、つまり挿入された値 1000 と 500 の合計に変化します。
SET @sum=0;
Query OK, 0 rows affected (0.05 sec)
mysql> INSERT INTO tb_emp8
-> VALUES(1,'A',1,1000),(2,'B',1,500);
Query OK, 2 rows affected (0.09 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> SELECT @sum;
+------+
| @sum |
+------+
| 1500 |
+------+
1 row in set (0.03 sec)
AFTER型トリガーの作成
test_db データベースでは、データ テーブル tb_emp6 と tb_emp7 は、どちらも id、name、deptId、給与フィールドを含む従業員情報テーブルであり、データ テーブル tb_emp6 と tb_emp7 のテーブル構造は次のとおりです。
mysql> SELECT * FROM tb_emp6;
Empty set (0.07 sec)
mysql> SELECT * FROM tb_emp7;
Empty set (0.03 sec)
mysql> DESC tb_emp6;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(25) | YES | | NULL | |
| deptId | int(11) | YES | MUL | NULL | |
| salary | float | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
mysql> DESC tb_emp7;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(25) | YES | | NULL | |
| deptId | int(11) | YES | | NULL | |
| salary | float | YES | | 0 | |
+--------+-------------+------+-----+---------+-------+
4 rows in set (0.04 sec)
[例 2] double_salary という名前のトリガを作成する トリガ条件は、データテーブル tb_emp6 にデータを挿入した後、同じデータをデータテーブル tb_emp7 に挿入し、給与が tb_emp6 に新しく挿入された給与フィールドの値の 2 であることです。回。入力SQL文と実行処理は以下のとおりです。
mysql> CREATE TRIGGER double_salary
-> AFTER INSERT ON tb_emp6
-> FOR EACH ROW
-> INSERT INTO tb_emp7
-> VALUES (NEW.id,NEW.name,deptId,2*NEW.salary);
Query OK, 0 rows affected (0.25 sec)
トリガー double_salary の作成後、レコードがテーブル tb_emp6 に挿入されると、同じレコードが同時にテーブル tb_emp7 に挿入され、次に示すように、給与フィールドは tb_emp6 の給与フィールドの値の 2 倍になります。
mysql> INSERT INTO tb_emp6
-> VALUES (1,'A',1,1000),(2,'B',1,500);
Query OK, 2 rows affected (0.09 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM tb_emp6;
+----+------+--------+--------+
| id | name | deptId | salary |
+----+------+--------+--------+
| 1 | A | 1 | 1000 |
| 2 | B | 1 | 500 |
+----+------+--------+--------+
3 rows in set (0.04 sec)
mysql> SELECT * FROM tb_emp7;
+----+------+--------+--------+
| id | name | deptId | salary |
+----+------+--------+--------+
| 1 | A | 1 | 2000 |
| 2 | B | 1 | 1000 |
+----+------+--------+--------+
2 rows in set (0.06 sec)
大昌上級データベースエンジニアmysqlデータベース実習https://edu.csdn.net/course/detail/39021