MySQL触发器(trigger)的用法(非常详细)
MySQL 触发器和存储过程一样,都是嵌入到 MySQL 的一段程序。
触发器是由事件来触发某个操作,这些事件包括 INSERT、UPDATAE 和 DELETE 语句。如果定义了触发程序,当数据库执行这些语句的时候,就会激发触发器执行相应的操作。触发程序是与表有关的命名数据库对象,当表上出现特定事件时,将激活该对象。
本节将通过实例来介绍触发器的含义、创建触发器、查看触发器、触发器的使用方法以及删除触发器。
触发器可以查询其他表,而且可以包含复杂的 SQL 语句。它们主要用于满足复杂的业务规则或要求。例如,可以根据客户当前的账户状态控制是否允许插入新订单。
【实例】创建只有一个执行语句的触发器,代码如下:
代码执行如下:
【实例】创建一个包含多个执行语句的触发器,代码如下:
下面将介绍两种查看触发器的方法,分别是 SHOW TRIGGERS 语句和在 TRIGGERS 表中查看触发器信息。
【实例】通过 SHOW TRIGGERS 语句查看一个触发器,代码如下:
创建一个简单的触发器,名称为 trig_update,每次在 account 表更新数据之后都会向名称为 myevent 的数据表中插入一条记录,数据表 myevent 定义如下:
创建触发器的执行代码如下:
使用 SHOW TRIGGERS 命令查看触发器:
提示,SHOW TRIGGERS 语句查看当前创建的所有触发器信息,在触发器较少的情况下,使用该语句会很方便。如果要查看特定触发器的信息,可以直接从 INFORMATION_SCHEMA 数据库中的 TRIGGERS 表中查找。下面将介绍这种方法。
【实例】通过 SELECT 命令查看触发器,代码如下:
上述命令通过 WHERE 来指定查看特定名称的触发器。指定触发器名称的执行情况如下:
也可以不指定触发器名称,这样将查看所有的触发器,命令如下:
触发程序与表相关,当对表执行 INSERT、DELETE 或 UPDATE 语句时,将激活触发程序。可以将触发程序设置为在执行语句之前或之后激活。例如,可以在从表中删除每一行之前或在更新每一行之后激活触发程序。
【实例】创建一个在 account 表插入记录之后更新 myevent 数据表的触发器,代码如下:
上面的代码创建了一个 trig_insert 触发器,在向表 account 插入数据之后,会向表 myevent 插入一组数据,代码执行如下:
【实例】删除一个触发器,代码如下:
触发器是由事件来触发某个操作,这些事件包括 INSERT、UPDATAE 和 DELETE 语句。如果定义了触发程序,当数据库执行这些语句的时候,就会激发触发器执行相应的操作。触发程序是与表有关的命名数据库对象,当表上出现特定事件时,将激活该对象。
本节将通过实例来介绍触发器的含义、创建触发器、查看触发器、触发器的使用方法以及删除触发器。
MySQL创建触发器
触发器(trigger)是一个特殊的存储过程,不同的是,执行存储过程要使用 CALL 语句来调用,而触发器的执行不需要使用 CALL 语句来调用,也不需要手工启动,只要当一个预定义的事件发生的时候,触发器就会被 MySQL 自动调用。比如,当对 fruits 表进行操作(INSERT、DELETE 或 UPDATE)时,就会激活它执行。触发器可以查询其他表,而且可以包含复杂的 SQL 语句。它们主要用于满足复杂的业务规则或要求。例如,可以根据客户当前的账户状态控制是否允许插入新订单。
1) 创建只有一个执行语句的触发器
创建一个触发器的语法如下:CREATE TRIGGER trigger_name trigger_time trigger_event ON tbl_name FOR EACH ROW trigger_stmt
- trigger_name 表示触发器名称,用户自行指定;
- trigger_time 表示触发时机,可以指定为 before 或 after;
- trigger_event 表示触发事件,包括 INSERT、UPDATE 和 DELETE;
- tbl_name 表示建立触发器的表名,即在哪张表上建立触发器;
- trigger_stmt 是触发器执行语句。
【实例】创建只有一个执行语句的触发器,代码如下:
CREATE TABLE account (acct_num INT, amount DECIMAL(10,2)); CREATE TRIGGER ins_sum BEFORE INSERT ON account FOR EACH ROW SET @sum = @sum + NEW.amount;首先,创建一个 account 表,表中有两个字段,分别为 acct_num 字段(定义为 int 类型)和 amount 字段(定义成浮点类型);其次,创建一个名为 ins_sum 的触发器,触发的条件是向数据表 account 插入数据之前,对新插入的 amount 字段值进行求和计算。
代码执行如下:
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; mysql>SET @sum =0; mysql> INSERT INTO account VALUES(1,1.00), (2,2.00); mysql> SELECT @sum; +------+ | @sum | +------+ | 3.00 | +------+首先,创建一个 account 表,在向表 account 插入数据之前,计算所有新插入的 account 表的 amount 值之和,触发器的名称为 ins_sum,条件是在向表插入数据之前触发。
2) 创建有多个执行语句的触发器
创建具有多个执行语句的触发器的语法如下:CREATE TRIGGER trigger_name trigger_time trigger_event ON tbl_name FOR EACH ROW BEGIN 语句执行列表 END
- trigger_name 标识触发器的名称,用户自行指定;
- trigger_time 标识触发时机,可以指定为 before 或 after;
- trigger_event 标识触发事件,包括 INSERT、UPDATE 和 DELETE;
- tbl_name 标识建立触发器的表名,即在哪张表上建立触发器;
- 触发器程序可以使用 BEGIN 和 END 作为开始和结束,中间包含多条语句。
【实例】创建一个包含多个执行语句的触发器,代码如下:
CREATE TABLE test1(a1 INT); CREATE TABLE test2(a2 INT); CREATE TABLE test3(a3 INT NOT NULL AUTO_INCREMENT PRIMARY KEY); CREATE TABLE test4( a4 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b4 INT DEFAULT 0 ); DELIMITER // CREATE TRIGGER testref BEFORE INSERT ON test1 FOR EACH ROW BEGIN INSERT INTO test2 SET a2 = NEW.a1; DELETE FROM test3 WHERE a3 = NEW.a1; UPDATE test4 SET b4 = b4 + 1 WHERE a4 = NEW.a1; END // DELIMITER ; INSERT INTO test3 (a3) VALUES (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL); INSERT INTO test4 (a4) VALUES (0), (0), (0), (0), (0), (0), (0), (0), (0), (0);上面的代码创建了一个名为 testref 的触发器。这个触发器的触发条件是在向表 test1 插入数据前执行触发器的语句,具体执行的代码如下:
mysql> INSERT INTO test1 VALUES (1), (3), (1), (7), (1), (8), (4), (4);4 个表中的数据如下:
mysql> SELECT * FROM test1; +----+ | a1 | +----+ | 1 | | 3 | | 1 | | 7 | | 1 | | 8 | | 4 | | 4 | +----+ 8 rows in set (0.00 sec) mysql> SELECT * FROM test2; +----+ | a2 | +----+ | 1 | | 3 | | 1 | | 7 | | 1 | | 8 | | 4 | | 4 | +----+ 8 rows in set (0.00 sec) mysql> SELECT * FROM test3; +----+ | a3 | +----+ | 2 | | 5 | | 6 | | 9 | | 10 | +----+ 5 rows in set (0.00 sec) mysql> SELECT * FROM test4; +----+----+ | a4 | b4 | +----+----+ | 1 | 3 | | 2 | 0 | | 3 | 1 | | 4 | 2 | | 5 | 0 | | 6 | 0 | | 7 | 1 | | 8 | 1 | | 9 | 0 | | 10 | 0 | +----+----+ 10 rows in set (0.00 sec)执行结果显示,在向表 test1 插入记录的时候,test2、test3、test4 都发生了变化。从这个例子看 INSERT 触发了触发器,向 test2 中插入了 test1 中的值,删除了 test3 中相同的内容,同时更新了 test4 中的 b4,即与插入的值相同的个数。
MySQL查看触发器
查看触发器是指查看数据库中已存在的触发器的定义、状态和语法信息等。可以通过命令来查看已经创建的触发器。下面将介绍两种查看触发器的方法,分别是 SHOW TRIGGERS 语句和在 TRIGGERS 表中查看触发器信息。
1) 利用SHOW TRIGGERS语句查看触发器信息
通过 SHOW TRIGGERS 查看触发器的语句如下:SHOW TRIGGERS;
【实例】通过 SHOW TRIGGERS 语句查看一个触发器,代码如下:
SHOW TRIGGERS;
创建一个简单的触发器,名称为 trig_update,每次在 account 表更新数据之后都会向名称为 myevent 的数据表中插入一条记录,数据表 myevent 定义如下:
CREATE TABLE myevent ( id int DEFAULT NULL, evt_name char(20) DEFAULT NULL ) ;
创建触发器的执行代码如下:
mysql> CREATE TRIGGER trig_update AFTER UPDATE ON account -> FOR EACH ROW INSERT INTO myevent VALUES (1,'after update'); Query OK, 0 rows affected (0.00 sec)
使用 SHOW TRIGGERS 命令查看触发器:
mysql> SHOW TRIGGERS; +------+-----+------+--------+------+-------+--------+-------+--------------------+-------- ------------+------------------+ |Trigger|Event|Table|Statement|Timing|Created|sql_mode|Definer|character_set_client|collati n_connection|Database Collation| +------+-----+------+--------+------+-------+--------+-------+--------------------+-------- ------------+------------------+ |ins_sum|INSERT|account| SET @sum = @sum + NEW.amount| BEFORE | NULL| | root@localhost|latin1| latin1_wedish_ci | latin1_swedish_ci | | trig_update | UPDATE | account | INSERT INTO myevent VALUES (1,'after update')| AFTER| NULL | |root@localhost | utf8mb4 | utf8mb4_0900_ai_ci | utf8mb4_0900_ai_ci| +------+-----+------+--------+------+-------+--------+-------+--------------------+-------- ------------+------------------+ 2 rows in set (0.00 sec)可以看到,信息显示比较混乱。如果在 SHOW TRIGGERS 命令的后面添加上“\G”,显示信息会比较有条理,执行情况如下:
mysql> SHOW TRIGGERS \G *************************** 1. row *************************** Trigger: ins_sum Event: INSERT Table: account Statement: SET @sum = @sum + NEW.amount Timing: BEFORE Created: 2022-03-17 09:27:50.92 sql_mode: STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION Definer: root@localhost character_set_client: utf8mb4 collation_connection: utf8mb4_0900_ai_ci Database Collation: utf8mb4_0900_ai_ci *************************** 2. row *************************** Trigger: trig_update Event: UPDATE Table: account Statement: INSERT INTO myevent VALUES (1,'after update') Timing: AFTER Created: 2022-03-17 09:33:51.49 sql_mode: STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION Definer: root@localhost character_set_client: utf8mb4 collation_connection: utf8mb4_0900_ai_ci Database Collation: utf8mb4_0900_ai_ci *************************** 3. row *************************** Trigger: testref Event: INSERT Table: test1 Statement: BEGIN INSERT INTO test2 SET a2 = NEW.a1; DELETE FROM test3 WHERE a3 = NEW.a1; UPDATE test4 SET b4 = b4 + 1 WHERE a4 = NEW.a1; END Timing: BEFORE Created: 2022-03-17 09:31:33.40 sql_mode: STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION Definer: root@localhost character_set_client: utf8mb4 collation_connection: utf8mb4_0900_ai_ci Database Collation: utf8mb4_0900_ai_ci
- Trigger 表示触发器的名称,在这里两个触发器的名称分别为 ins_sum 和 trig_update;
- Event 表示激活触发器的事件,这里的两个触发事件为插入操作 INSERT 和更新操作 UPDATE;
- Table 表示激活触发器的操作对象表,这里都为 account 表;
- Timing 表示触发器触发的时间,分别为插入操作之前(BEFORE)和更新操作之后(AFTER);
- Statement 表示触发器执行的操作,还有一些其他信息,比如 SQL 的模式、触发器的定义账户和字符集等,这里不再一一介绍。
提示,SHOW TRIGGERS 语句查看当前创建的所有触发器信息,在触发器较少的情况下,使用该语句会很方便。如果要查看特定触发器的信息,可以直接从 INFORMATION_SCHEMA 数据库中的 TRIGGERS 表中查找。下面将介绍这种方法。
2) 在triggers表中查看触发器信息
在 MySQL 中,所有触发器的定义都存在 INFORMATION_SCHEMA 数据库的 TRIGGERS 表中,可以通过查询命令 SELECT 查看,具体的语法如下:SELECT * FROM INFORMATION_SCHEMA.TRIGGERS WHERE condition;
【实例】通过 SELECT 命令查看触发器,代码如下:
SELECT * FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME= 'trig_update'\G
上述命令通过 WHERE 来指定查看特定名称的触发器。指定触发器名称的执行情况如下:
*************************** 1. row *************************** TRIGGER_CATALOG: def TRIGGER_SCHEMA: test_db TRIGGER_NAME: trig_update EVENT_MANIPULATION: UPDATE EVENT_OBJECT_CATALOG: def EVENT_OBJECT_SCHEMA: test_db EVENT_OBJECT_TABLE: account ACTION_ORDER: 1 ACTION_CONDITION: NULL ACTION_STATEMENT: INSERT INTO myevent VALUES (1,'after update') ACTION_ORIENTATION: ROW ACTION_TIMING: AFTER ACTION_REFERENCE_OLD_TABLE: NULL ACTION_REFERENCE_NEW_TABLE: NULL ACTION_REFERENCE_OLD_ROW: OLD ACTION_REFERENCE_NEW_ROW: NEW CREATED: 2022-03-17 09:33:51.49 SQL_MODE: STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION DEFINER: root@localhost CHARACTER_SET_CLIENT: utf8mb4 COLLATION_CONNECTION: utf8mb4_0900_ai_ci DATABASE_COLLATION: utf8mb4_0900_ai_ci从上面的执行结果可以得知:
- TRIGGER_SCHEMA 表示触发器所在的数据库;
- TRIGGER_NAME 后面是触发器的名称;
- EVENT_OBJECT_TABLE 表示在哪个数据表上触发;
- ACTION_STATEMENT 表示触发器触发的时候执行的具体操作;
- ACTION_ORIENTATION 是 ROW,表示在每条记录上都触发;
- ACTION_TIMING 表示触发的时刻是 AFTER;剩下的是和系统相关的信息。
也可以不指定触发器名称,这样将查看所有的触发器,命令如下:
SELECT * FROM INFORMATION_SCHEMA.TRIGGERS \G这个命令会显示 TRIGGERS 表中所有的触发器信息,读者自行测试一下。
MySQL触发器的使用
触发程序是与表有关的命名数据库对象,当表上出现特定事件时,将激活该对象。在某些触发程序的用法中,可用于检查插入到表中的值,或对更新涉及的值进行计算。触发程序与表相关,当对表执行 INSERT、DELETE 或 UPDATE 语句时,将激活触发程序。可以将触发程序设置为在执行语句之前或之后激活。例如,可以在从表中删除每一行之前或在更新每一行之后激活触发程序。
【实例】创建一个在 account 表插入记录之后更新 myevent 数据表的触发器,代码如下:
CREATE TRIGGER trig_insert AFTER INSERT ON account FOR EACH ROW INSERT INTO myevent VALUES (2,'after insert');
上面的代码创建了一个 trig_insert 触发器,在向表 account 插入数据之后,会向表 myevent 插入一组数据,代码执行如下:
mysql> CREATE TRIG?GER trig_insert AFTER INSERT ON account -> FOR EACH ROW INSERT INTO myevent VALUES (2, 'after insert '); mysql> INSERT INTO account VALUES (1,1.00), (2,2.00); mysql> SELECT * FROM myevent; +------+--------------+ | id | evt_name | +------+--------------+ | 2 | after insert | | 2 | after insert | +------+--------------+从执行的结果来看,创建了一个名称为 trig_insert 的触发器,在向 account 插入记录之后进行触发,执行的操作是向表 myevent 插入一条记录。
MySQL删除触发器
使用 DROP TRIGGER 语句可以删除 MySQL 中已经定义的触发器,删除触发器语句的基本语法格式如下:DROP TRIGGER [schema_name.]trigger_name其中,schema_name 表示数据库名称,是可选的。如果省略了 schema,将从当前数据库中舍弃触发程序;trigger_name 是要删除的触发器的名称。
【实例】删除一个触发器,代码如下:
DROP TRIGGER test_db.ins_sum;上面的代码中 test 是触发器所在的数据库,ins_sum 是一个触发器的名称。代码执行如下:
mysql> DROP TRIGGER test_db.ins_sum; Query OK, 0 rows affected (0.00 sec)触发器 ins_sum 删除成功。