SQL触发器是依附于数据库表的一种特殊对象,当表发生INSERT、UPDATE、DELETE等操作时,会自动触发执行预设的SQL逻辑,不需要手动调用就能完成对应的数据处理任务,在数据库自动化场景中应用十分广泛。

SQL触发器的核心概念
触发器本质上是和表绑定的事件驱动程序,它的执行完全由数据操作事件触发,开发者无法主动调用。按照触发时机可以分为两类:
- BEFORE触发器:在数据操作执行之前触发,常用于数据合法性校验、预处理等操作。
- AFTER触发器:在数据操作执行完成之后触发,常用于记录操作日志、同步关联表数据等操作。
按照触发事件可以分为INSERT触发器、UPDATE触发器、DELETE触发器,分别对应三种数据操作场景。在MySQL、PostgreSQL等数据库中,还可以通过OLD和NEW关键字获取操作前后的数据,OLD代表操作前的行数据,NEW代表操作后的行数据。
SQL触发器的创建语法
MySQL中创建触发器
MySQL的触发器创建语法如下,需要注意每个表针对同一事件同一时机只能创建一个触发器:
-- 创建AFTER INSERT触发器,当向user表插入数据后,自动向user_log表记录日志
DELIMITER //
CREATE TRIGGER after_user_insert
AFTER INSERT ON user
FOR EACH ROW
BEGIN
-- 插入操作日志,NEW.id代表新插入的用户ID,NEW.name代表新插入的用户名
INSERT INTO user_log (user_id, user_name, operation_type, operation_time)
VALUES (NEW.id, NEW.name, 'INSERT', NOW());
END //
DELIMITER ;PostgreSQL中创建触发器
PostgreSQL需要先创建触发器函数,再绑定到表上,语法和MySQL略有区别:
-- 先创建触发器函数
CREATE OR REPLACE FUNCTION log_user_insert()
RETURNS TRIGGER AS $$
BEGIN
-- 插入操作日志
INSERT INTO user_log (user_id, user_name, operation_type, operation_time)
VALUES (NEW.id, NEW.name, 'INSERT', NOW());
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- 再绑定触发器到user表
CREATE TRIGGER after_user_insert
AFTER INSERT ON user
FOR EACH ROW
EXECUTE FUNCTION log_user_insert();SQL触发器的常见使用场景
自动记录数据操作日志
这是触发器最常用的场景,比如用户表数据发生变更时,自动把变更信息记录到日志表,不需要在业务代码中每次操作都写日志插入逻辑:
-- MySQL中创建AFTER UPDATE触发器,记录用户更新日志
DELIMITER //
CREATE TRIGGER after_user_update
AFTER UPDATE ON user
FOR EACH ROW
BEGIN
-- 只有用户名或者手机号发生变更时才记录日志
IF OLD.name != NEW.name OR OLD.phone != NEW.phone THEN
INSERT INTO user_log (user_id, user_name, operation_type, operation_time, old_value, new_value)
VALUES (NEW.id, NEW.name, 'UPDATE', NOW(),
CONCAT('旧名称:', OLD.name, ',旧手机:', OLD.phone),
CONCAT('新名称:', NEW.name, ',新手机:', NEW.phone));
END IF;
END //
DELIMITER ;数据合法性校验
可以在BEFORE触发器中校验插入或更新的数据是否符合要求,不符合要求时直接抛出异常阻止操作:
-- MySQL中创建BEFORE INSERT触发器,校验用户年龄不能为负数
DELIMITER //
CREATE TRIGGER before_user_insert
BEFORE INSERT ON user
FOR EACH ROW
BEGIN
-- 如果年龄小于0,抛出异常
IF NEW.age < 0 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '用户年龄不能为负数';
END IF;
END //
DELIMITER ;关联表数据同步
当主表数据发生变更时,自动同步更新关联的统计表数据,比如用户表新增数据时,自动更新用户总数统计表:
-- MySQL中创建AFTER INSERT触发器,同步更新用户统计表
DELIMITER //
CREATE TRIGGER after_user_insert_sync
AFTER INSERT ON user
FOR EACH ROW
BEGIN
-- 更新用户总数,加1
UPDATE user_stat SET total_count = total_count + 1 WHERE stat_date = CURDATE();
-- 如果当天没有统计记录,先插入一条
IF ROW_COUNT() = 0 THEN
INSERT INTO user_stat (stat_date, total_count) VALUES (CURDATE(), 1);
END IF;
END //
DELIMITER ;SQL触发器的使用注意事项
- 触发器执行会占用数据库资源,过于复杂的触发器逻辑会影响数据操作的性能,建议触发器逻辑尽量简单。
- 触发器是隐式执行的,问题排查时如果不熟悉触发器逻辑,很容易忽略触发器的执行影响,建议给触发器起清晰的名称,并且做好相关文档记录。
- 不同数据库的触发器语法存在差异,迁移数据库时需要对应调整触发器的实现方式。
- 避免在一个表上创建过多触发器,否则数据操作时会触发多个逻辑,增加维护难度。
注意:如果业务逻辑的触发条件比较复杂,或者需要跨系统调用,建议优先考虑在业务层实现,触发器的适用场景更适合数据库层面的简单自动化操作。