触发器
MySQL的触发器和存储过程一样,都是嵌入到MySQL的一段程序。触发器是由事件来触发某个操作,这些事件包括INSERT、UPDATAE和DELETE语句。如果定义了触发程序,当数据库执行这些语句的时候就会激发触发器执行相应的操作,触发程序是与表有关的命名数据库对象,当表上出现特定事件时,将激活该对象。
1、创建触发器
触发器(trigger)是一个特殊的存储过程,不同的是,执行存储过程要使用CALL语句来调用,而触发器的执行不需要使用CALL语句来调用,也不需要手工启动,只要当一个预定义的事件发生的时候,就会被MySQL自动调用。比如当对fruits表进行操作(INSERT、DELETE或UPDATE)时就会激活它执行。
触发器可以查询其他表,而且可以包含复杂的SQL语句。它们主要用于满足复杂的业务规则或要求。例如,可以根据客户当前的账户状态控制是否允许插入新订单。
1.1、创建只有一个执行语句的触发器
创建一个触发器的语法如下:
sql
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是触发器执行语句。
创建一个单执行语句的触发器,代码如下:
sql
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字段值进行求和计算。
sql
set @sum = 0;
insert into account values(1, 1.00), (2, 2.00);
select * from account;
+----------+--------+
| acct_num | amount |
+----------+--------+
| 1 | 1.00 |
| 2 | 2.00 |
+----------+--------+
select @sum;
+------+
| @sum |
+------+
| 3.00 |
+------+
首先,创建一个account表,在向表account插入数据之前,计算所有新插入的account表的amount值之和,触发器的名称为ins_sum,条件是在向表插入数据之前触发。
1.2、创建有多个执行语句的触发器
创建多个执行语句的触发器的语法如下:
sql
CREATE TRIGGER trigger_name trigger_time trigger_event
ON tb1_name FOR EACH ROW
BEGIN
语句执行列表
END
- trigger_name标识触发器的名称,用户自行指定;
- trigger_time标识触发时机,可以指定为before或after;
- trigger_event标识触发事件,包括INSERT、UPDATE和DELETE;
- tbl_name标识建立触发器的表名,即在哪张表上建立触发器;
- 触发器程序可以使用BEGIN和END作为开始和结束,中间包含多条语句。
创建一个包含多个执行语句的触发器,代码如下:
sql
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);
insert into test4(a4) values
(0), (0), (0), (0), (0), (0), (0), (0), (0), (0);
上面的代码创建了一个名为testref的触发器。这个触发器的触发条件是在向表test1插入数据前执行触发器的语句,具体执行的代码如下:
sql
insert into test1 values
(1), (3), (1), (7), (1), (8), (4), (4);
4个表中的数据如下:
sql
select * from test1;
+----+
| a1 |
+----+
| 1 |
| 3 |
| 1 |
| 7 |
| 1 |
| 8 |
| 4 |
| 4 |
+----+
sql
select * from test2;
+----+
| a2 |
+----+
| 1 |
| 3 |
| 1 |
| 7 |
| 1 |
| 8 |
| 4 |
| 4 |
+----+
sql
select * from test3;
+----+
| a3 |
+----+
| 2 |
| 5 |
| 6 |
+----+
sql
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 |
+----+----+
执行结果显示,在向表test1插入记录的时候,test2、test3、test4都发生了变化。从这个例子看INSERT触发了触发器,向test2中插入了test1中的值,删除了test3中相同的内容,同时更新了test4中的b4,即与插入的值相同的个数。
2、查看触发器
查看触发器是指查看数据库中已存在的触发器的定义、状态和语法信息等。可以通过命令来查看已经创建的触发器。
两种查看触发器的方法,分别是SHOWTRIGGERS和在triggers表中查看触发器信息。
2.1、利用SHOW TRIGGERS语句查看触发器信息
通过SHOW TRIGGERS查看触发器的语句如下:
sql
SHOW TRIGGERS;
通过SHOW TRIGGERS命令查看一个触发器,代码如下:
sql
show triggers;
***************************[ 1. row ]***************************
Trigger | ins_sum
Event | INSERT
Table | account
Statement | set @sum = @sum + NEW.amount
Timing | BEFORE
Created | 2026-06-25 21:50:31.090000
***************************[ 1. row ]***************************
Trigger | ins_sum
Event | INSERT
Table | account
Statement | set @sum = @sum + NEW.amount
Timing | BEFORE
Created | 2026-06-25 21:50:31.090000
***************************[ 1. row ]***************************
Trigger | ins_sum
Event | INSERT
Table | account
Statement | set @sum = @sum + NEW.amount
Timing | BEFORE
Created | 2026-06-25 21:50:31.090000
sql_mode | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
Definer | root@%
character_set_client | utf8mb4
collation_connection | utf8mb4_0900_ai_ci
Database Collation | utf8mb3_general_ci
***************************[ 2. 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 | 2026-06-25 21:58:25.100000
sql_mode | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
Definer | root@%
character_set_client | utf8mb4
collation_connection | utf8mb4_0900_ai_ci
Database Collation | utf8mb3_general_ci
创建一个简单的触发器,名称为trig_update,每次向account表更新数据之后都会向名称为myevent的数据表中插入一条记录,数据表myevent定义如下:
sql
create table myevent
(
id int(11) default null,
evt_name char(20) default null
);
创建触发器的执行代码如下:
sql
create trigger trig_update
after update on account
for each row
insert into myevent values(1, 'after update');
使用SHOW TRIGGERS命令查看触发器:
sql
show triggers \G;
***************************[ 1. row ]***************************
Trigger | ins_sum
Event | INSERT
Table | account
Statement | set @sum = @sum + NEW.amount
Timing | BEFORE
Created | 2026-06-25 21:50:31.090000
sql_mode | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
Definer | root@%
character_set_client | utf8mb4
collation_connection | utf8mb4_0900_ai_ci
Database Collation | utf8mb3_general_ci
***************************[ 2. row ]***************************
Trigger | trig_update
Event | UPDATE
Table | account
Statement | insert into myevent values(1, 'after update')
Timing | AFTER
Created | 2026-06-25 22:10:09.490000
sql_mode | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
Definer | root@%
character_set_client | utf8mb4
- Trigger表示触发器的名称,在这里两个触发器的名称分别为ins_sum和trig_update;
- Event表示激活触发器的事件,这里的两个触发事件为插入操作INSERT和更新操作UPDATE;
- Table表示激活触发器的操作对象表,这里都为account表;
- Timing表示触发器触发的时间,分别为插入操作之前(BEFORE)和更新操作之后(AFTER);
- Statement表示触发器执行的操作
- 还有一些其他信息,比如sql的模式、触发器的定义账户和字符集等
2.2、在triggers表中查看触发器信息
在MySQL中,所有触发器的定义都存在INFORMATION_SCHEMA数据库的TRIGGERS表格中,可以通过查询命令SELECT查看,具体的语法如下:
sql
SELECT * FROM INFORMATION_SCHEMA.TRIGGERS WHERE condition;
通过SELECT命令查看触发器,代码如下:
sql
SELECT * FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME= 'trig_update'\G;
***************************[ 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 | 2026-06-25 22:10:09.490000
SQL_MODE | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
DEFINER | root@%
CHARACTER_SET_CLIENT | utf8mb4
COLLATION_CONNECTION | utf8mb4_0900_ai_ci
DATABASE_COLLATION | utf8mb3_general_ci
从上面的执行结果可以得知:
- TRIGGER_SCHEMA表示触发器所在的数据库;
- TRIGGER_NAME后面是触发器的名称;
- EVENT_OBJECT_TABLE表示在哪个数据表上触发;
- ACTION_STATEMENT表示触发器触发的时候执行的具体操作;
- ACTION_ORIENTATION是ROW,表示在每条记录上都触发;
- ACTION_TIMING表示触发的时刻是AFTER;
- 剩下的是和系统相关的信息。
也可以不指定触发器名称,这样将查看所有的触发器,命令如下:
sql
SELECT * FROM INFORMATION_SCHEMA.TRIGGERS \G
这个命令会显示TRIGGERS表中所有的触发器信息。
3、触发器的使用
触发程序是与表有关的命名数据库对象,当表上出现特定事件时,将激活该对象。在某些触发程序的用法中,可用于检查插入到表中的值,或对更新涉及的值进行计算。
触发程序与表相关,当对表执行INSERT、DELETE或UPDATE语句时,将激活触发程序。可以将触发程序设置为在执行语句之前或之后激活。例如,可以在从表中删除每一行之前或在更新每一行之后激活触发程序。
创建一个在account表插入记录之后更新myevent数据表的触发器,代码如下:
sql
create trigger trig_insert
after insert on account
for each row
insert into myevent values(2, 'after insert');
上面的代码创建了一个trig_insert触发器,在向表account插入数据之后会向表myevent插入一组数据,代码执行如下:
sql
insert into account values
(1, 1.00), (2, 2.00);
select * from myevent;
+----+--------------+
| id | evt_name |
+----+--------------+
| 2 | after insert |
| 2 | after insert |
+----+--------------+
从执行的结果来看,创建了一个名称为trig_insert的触发器,在向account插入记录之后进行触发,执行的操作是向表myevent插入一条记录。
4、删除触发器
使用DROP TRIGGER语句可以删除MySQL中已经定义的触发器,删除触发器语句的基本语法格式如下:
sql
DROP TRIGGER [schema_name.]trigger_name
- schema_name表示数据库名称,是可选的。如果省略了schema,将从当前数据库中舍弃触发程序;
- trigger_name是要删除的触发器的名称;
删除一个触发器,代码如下:
sql
drop trigger test_db.ins_sum;
Query OK, 0 rows affected
Time: 0.072s
5、综合案例
下面是创建触发器的实例,每更新一次persons表的num字段后都要更新sales表对应的sum字段。其中,persons表结构如表所示:

sales表结构如表所示:

persons表内容如表所示:

1. 创建一个业务统计表persons。
创建一个业务统计表persons,代码如下:
sql
create table persons(
name varchar(40),
num int
);
2. 创建一个销售额表sales。
创建一个销售额表sales,代码如下:
sql
create table sales
(
name varchar(40),
sum int
);
3. 创建一个触发器。
创建一个触发器,在更新过persons表的num字段后,更新sales表的sum字段,代码如下:
sql
create trigger num_sum
after insert on persons
for each row
insert into sales values(NEW.name, 7 * NEW.num);
4. 向persons表中插入记录。
插入新的记录后,更新销售额表。
sql
insert into persons values
('xiaoxiao', 20), ('xiaohua', 69);
结果如下:
sql
select * from persons;
+----------+-----+
| name | num |
+----------+-----+
| xiaoxiao | 20 |
| xiaohua | 69 |
+----------+-----+
select * from sales;
+----------+-----+
| name | sum |
+----------+-----+
| xiaoxiao | 140 |
| xiaohua | 483 |
+----------+-----+
从执行的结果来看,在persons表插入记录之后,num_sum触发器计算插入到persons表中的数据,并将结果插入到sales表中相应的位置。
6、常见问题
6.1、使用触发器时要特别注意的事项
使用触发器的时候需要注意,对于相同的表,相同的事件只能创建一个触发器,比如对表account创建了一个BEFORE INSERT触发器,那么如果对表account再次创建一个BEFORE INSERT触发器,MySQL将会报错,此时,只可以在表account上创建AFTER INSERT或者BEFORE UPDATE类型的触发器。灵活地运用触发器将为操作省去很多麻烦。
6.2、及时删除不再需要的触发器
触发器定义之后,每次执行触发事件都会激活触发器并执行触发器中的语句。如果需求发生变化,而触发器没有进行相应的改变或者删除,则触发器仍然会执行旧的语句,从而会影响新的数据完整性。因此,要将不再使用的触发器及时删除。