在数据库业务场景中,我们常常需要在数据写入、修改、删除时校验业务逻辑,不符合规则的操作需要被直接拦截。MySQL的触发器可以在数据操作前或操作后自动执行自定义逻辑,结合SIGNAL SQLSTATE语法就能主动抛出自定义异常,终止非法操作并返回明确的错误信息,比单纯靠应用层校验更可靠。

触发器的基本使用规则
触发器是与表关联的数据库对象,会在表的INSERT、UPDATE、DELETE操作触发时执行,常见的触发时机分为BEFORE和AFTER两种:
- BEFORE触发器:在数据操作执行前触发,适合做数据校验、拦截非法操作
- AFTER触发器:在数据操作执行后触发,适合做关联表的同步更新、操作日志记录
创建触发器的基础语法如下:
-- 创建BEFORE INSERT触发器示例
CREATE TRIGGER trigger_name
BEFORE INSERT ON table_name
FOR EACH ROW
BEGIN
-- 触发器逻辑
END;
SIGNAL SQLSTATE语法说明
SIGNAL SQLSTATE用于主动抛出一个带有指定错误码和错误信息的异常,终止当前正在执行的操作。其基本语法结构为:
SIGNAL SQLSTATE '错误码' SET MESSAGE_TEXT = '错误提示信息';
其中错误码需要符合SQLSTATE规范,自定义业务错误通常选择45000到45999之间的错误码,这部分区间是MySQL预留给用户自定义的错误码范围,不会和系统的内置错误码冲突。
用触发器拦截非法操作的实战案例
案例1:阻止插入年龄不合法的员工数据
假设有一张员工表employee,要求员工的年龄必须在18到60岁之间,否则插入操作需要被拦截。我们可以创建BEFORE INSERT触发器实现这个校验:
-- 创建员工表
CREATE TABLE employee (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
age INT NOT NULL,
salary DECIMAL(10,2)
);
-- 创建插入前校验的触发器
CREATE TRIGGER check_employee_age_insert
BEFORE INSERT ON employee
FOR EACH ROW
BEGIN
-- 判断新插入的年龄是否不在合法范围
IF NEW.age < 18 OR NEW.age > 60 THEN
-- 抛出自定义异常,终止插入操作
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '员工年龄必须在18到60岁之间,当前插入的年龄不合法';
END IF;
END;
当我们尝试插入年龄不符合要求的数据时,触发器会直接抛出异常,阻止操作执行:
-- 尝试插入年龄15的员工,会触发异常
INSERT INTO employee (name, age, salary) VALUES ('张三', 15, 5000);
-- 执行后会返回错误提示:员工年龄必须在18到60岁之间,当前插入的年龄不合法
案例2:阻止更新员工薪资为负数
如果还需要限制员工薪资不能为负数,不管是新增还是更新操作都不允许,我们可以再创建一个BEFORE UPDATE触发器:
-- 创建更新前校验的触发器
CREATE TRIGGER check_employee_salary_update
BEFORE UPDATE ON employee
FOR EACH ROW
BEGIN
-- 判断更新后的薪资是否为负数
IF NEW.salary < 0 THEN
SIGNAL SQLSTATE '45001'
SET MESSAGE_TEXT = '员工薪资不能为负数,请填写正确的薪资数值';
END IF;
END;
当执行更新操作将薪资改为负数时,触发器会拦截操作:
-- 先插入一条合法数据
INSERT INTO employee (name, age, salary) VALUES ('李四', 25, 8000);
-- 尝试将薪资更新为负数,触发异常
UPDATE employee SET salary = -1000 WHERE id = 1;
-- 执行后返回错误提示:员工薪资不能为负数,请填写正确的薪资数值
使用注意事项
- 触发器中抛出自定义异常后,整个数据操作会回滚,已经执行的部分逻辑不会生效
- 自定义错误码尽量使用45000到45999区间,避免和系统内置错误码冲突
- 错误提示信息尽量清晰,方便开发人员快速定位问题原因
- 不要在AFTER触发器中执行SIGNAL SQLSTATE,因为AFTER触发器执行时数据操作已经提交,抛出异常也无法回滚数据
- 如果触发器逻辑比较复杂,需要注意MySQL的触发器不支持事务显式控制,异常抛出后由外层事务决定是否回滚
MySQL触发器SIGNAL_SQLSTATE自定义异常数据库约束修改时间:2026-06-29 10:03:30