-- 示例:自动维护数据一致性 CREATETRIGGER check_balance BEFORE UPDATEON accounts FOREACHROW BEGIN IF NEW.balance <0THEN SIGNAL SQLSTATE'45000'SET MESSAGE_TEXT ='余额不足'; END IF; END;
-- 需要分别删除 DROPTRIGGER IF EXISTS trigger_student_count_insert; DROPTRIGGER IF EXISTS trigger_student_count_delete; DROPTRIGGER IF EXISTS trigger_student_count_update;
-- 查看触发器的使用情况 SELECT*FROM information_schema.triggers WHERE TRIGGER_NAME ='trigger_name';
3. 备份触发器定义
1 2 3 4 5 6 7
-- 删除前备份触发器定义 SHOW TRIGGERS\G
-- 或导出到文件 SELECT*FROM information_schema.triggers WHERE TRIGGER_SCHEMA ='db1' INTO OUTFILE '/tmp/triggers_backup.sql';
6. 触发器高级应用
6.1 BEFORE触发器应用
数据验证
1 2 3 4 5 6 7 8 9 10
-- 创建BEFORE INSERT触发器:插入前验证数据 CREATETRIGGER validate_student_before_insert BEFORE INSERTON student_info FOREACHROW BEGIN IF NEW.stu_name ISNULLOR NEW.stu_name =''THEN SIGNAL SQLSTATE'45000' SET MESSAGE_TEXT ='学生姓名不能为空'; END IF; END;
数据转换
1 2 3 4 5 6 7
-- 创建BEFORE INSERT触发器:自动转换数据格式 CREATETRIGGER format_student_name BEFORE INSERTON student_info FOREACHROW BEGIN SET NEW.stu_name =UPPER(TRIM(NEW.stu_name)); END;
自动生成字段
1 2 3 4 5 6 7 8 9
-- 创建BEFORE INSERT触发器:自动生成ID CREATETRIGGER generate_student_id BEFORE INSERTON student_info FOREACHROW BEGIN IF NEW.stu_id ISNULLTHEN SET NEW.stu_id = (SELECTCOALESCE(MAX(stu_id), 0) +1FROM student_info); END IF; END;
-- 创建AFTER UPDATE触发器:同步数据到缓存表 CREATETRIGGER sync_student_cache AFTER UPDATEON student_info FOREACHROW BEGIN UPDATE student_cache SET stu_name = NEW.stu_name, updated_at = NOW() WHERE stu_id = NEW.stu_id; END;
6.3 复杂业务逻辑触发器
级联更新
1 2 3 4 5 6 7 8 9
-- 创建级联更新触发器 CREATETRIGGER cascade_update_student AFTER UPDATEON student_info FOREACHROW BEGIN -- 更新相关表 UPDATE student_scores SET student_name = NEW.stu_name WHERE student_id = NEW.stu_id; UPDATE student_classes SET student_name = NEW.stu_name WHERE student_id = NEW.stu_id; END;
条件判断
1 2 3 4 5 6 7 8 9 10
-- 创建条件触发器 CREATETRIGGER conditional_update AFTER UPDATEON student_info FOREACHROW BEGIN IF NEW.stu_name != OLD.stu_name THEN INSERTINTO name_change_log(stu_id, old_name, new_name, change_time) VALUES(NEW.stu_id, OLD.stu_name, NEW.stu_name, NOW()); END IF; END;
7. 触发器最佳实践
7.1 触发器设计原则
1. 保持简单
1 2 3 4 5 6 7 8
-- 推荐:简单的触发器 CREATETRIGGER simple_trigger AFTER INSERTON table_name FOREACHROW UPDATE statistics SET count = count +1;
-- 不推荐:复杂的业务逻辑 -- 复杂逻辑应该在应用层实现
2. 避免递归触发
1 2
-- 注意:避免触发器调用会触发其他触发器的操作 -- 可能导致无限循环
3. 错误处理
1 2 3 4 5 6 7 8 9 10
-- 使用SIGNAL抛出错误 CREATETRIGGER validate_data BEFORE INSERTON table_name FOREACHROW BEGIN IF NEW.amount <0THEN SIGNAL SQLSTATE'45000' SET MESSAGE_TEXT ='金额不能为负数'; END IF; END;
7.2 性能优化
1. 避免在触发器中执行耗时操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14
-- 不推荐:在触发器中执行复杂查询 CREATETRIGGER slow_trigger AFTER INSERTON table_name FOREACHROW BEGIN -- 复杂的JOIN查询 SELECTCOUNT(*) FROM large_table WHERE ...; END;
-- 推荐:使用简单的更新操作 CREATETRIGGER fast_trigger AFTER INSERTON table_name FOREACHROW UPDATE counter SET count = count +1;
2. 批量操作考虑
1 2 3
-- 注意:触发器对每一行都会执行 -- 批量插入1000条数据,触发器会执行1000次 INSERTINTO table_name SELECT ... FROM large_table;
7.3 调试技巧
1. 使用临时表记录调试信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
-- 创建调试表 CREATETABLE trigger_debug ( id INT AUTO_INCREMENT PRIMARY KEY, trigger_name VARCHAR(50), message TEXT, debug_time DATETIME DEFAULTCURRENT_TIMESTAMP );
-- 在触发器中记录调试信息 CREATETRIGGER debug_trigger AFTER INSERTON table_name FOREACHROW BEGIN INSERTINTO trigger_debug(trigger_name, message) VALUES('debug_trigger', CONCAT('Inserted ID: ', NEW.id)); END;
2. 使用SELECT输出调试信息
1 2 3 4 5 6 7
-- 在触发器中输出调试信息(仅开发环境) CREATETRIGGER debug_trigger AFTER INSERTON table_name FOREACHROW BEGIN SELECT CONCAT('Debug: ', NEW.id) AS debug_info; END;