1. 首页 > MySQL教程 > 正文

MySQL教程FG126-MySQL触发器触发时机

内容简介:本文主要介绍MySQL存储过程参数与返回值的相关知识,包括参数类型、使用方法和最佳实践等内容。风哥教程参考MySQL官方文档MySQL Triggers、MySQL Server Administration。 01 更多视频教程www.fgedu.net.cn 02 学习交流加群风哥微信: itpux-com 03 学习交流加群风哥QQ113257174

Part01-基础概念与理论知识

1.1 触发时机类型

MySQL触发器支持两种触发时机:BEFORE和AFTER。BEFORE触发器在操作执行前触发,AFTER触发器在操作执行后触发。 04 风哥提示: 05更多学习教程公众号风哥教程itpux_com 06 from mysql视频:www.itpux.com

# 触发时机类型

1. BEFORE触发器
– 在INSERT、UPDATE、DELETE操作执行前触发
– 可以修改NEW值(INSERT和UPDATE)
– 不能修改OLD值
– 常用于数据验证和预处理

2. AFTER触发器
– 在INSERT、UPDATE、DELETE操作执行后触发
– 不能修改NEW或OLD值
– 数据已经写入表
– 常用于审计和日志记录

Part02-生产环境规划与建议

2.1 BEFORE触发器使用

# BEFORE触发器示例

1. 数据验证触发器
DELIMITER //

CREATE TRIGGER before_order_insert_validate
BEFORE INSERT ON orders
FOR EACH ROW
BEGIN
DECLARE user_status INT;

SELECT status INTO user_status
FROM users
WHERE id = NEW.user_id;

IF user_status IS NULL THEN
SIGNAL SQLSTATE ‘45000’
SET MESSAGE_TEXT = ‘用户不存在’;
END IF;

IF user_status = 0 THEN
SIGNAL SQLSTATE ‘45000’
SET MESSAGE_TEXT = ‘用户已被禁用,不能下单’;
END IF;

IF NEW.amount <= 0 THEN
SIGNAL SQLSTATE ‘45000’
SET MESSAGE_TEXT = ‘订单金额必须大于0’;
END IF;
END //

DELIMITER ;

输出示例:
Query OK, 0 rows affected (0.01 sec)

2. 测试验证触发器
INSERT INTO orders (user_id, amount) VALUES (1, 100.00);

输出示例:
Query OK, 1 row affected (0.01 sec)

3. 测试禁用用户下单
INSERT INTO orders (user_id, amount) VALUES (2, 100.00);

输出示例:
ERROR 1644 (45000): 用户已被禁用,不能下单

4. 数据预处理触发器
DELIMITER //

CREATE TRIGGER before_user_insert_preprocess
BEFORE INSERT ON users
FOR EACH ROW
BEGIN
NEW.user_name = TRIM(NEW.user_name);
NEW.email = LOWER(TRIM(NEW.email));

IF NEW.status IS NULL THEN
SET NEW.status = 1;
END IF;

IF NEW.created_at IS NULL THEN
SET NEW.created_at = NOW();
END IF;
END //

DELIMITER ;

输出示例:
Query OK, 0 rows affected (0.01 sec)

5. 测试预处理触发器
INSERT INTO users (user_name, email)
VALUES (‘ TestUser ‘, ‘ TEST@EXAMPLE.COM ‘);

输出示例:
Query OK, 1 row affected (0.01 sec)

6. 查看预处理结果
SELECT user_name, email, status, created_at FROM users WHERE user_name = ‘TestUser’;

输出示例:
+———–+——————-+——–+———————+
| user_name | email | status | created_at |
+———–+——————-+——–+———————+
| TestUser | test@fgedu.net.cn | 1 | 2026-04-04 10:30:00 |
+———–+——————-+——–+———————+
1 row in set (0.00 sec)

Part03-生产环境项目实施方案

3.1 AFTER触发器使用

# AFTER触发器示例

1. 审计日志触发器
DELIMITER //

CREATE TRIGGER after_user_audit
AFTER INSERT ON users
FOR EACH ROW
BEGIN
INSERT INTO user_audit_log (user_id, action, action_time, ip_address, user_agent)
VALUES (NEW.id, ‘CREATE’, NOW(), CONNECTION_ID(), ‘SYSTEM’);
END //

DELIMITER ;

输出示例:
Query OK, 0 rows affected (0.01 sec)

2. 测试审计触发器
INSERT INTO users (user_name, email, status, created_at)
VALUES (‘audit_user’, ‘audit@test.com’, 1, NOW());

输出示例:
Query OK, 1 row affected (0.01 sec)

3. 查看审计日志
SELECT * FROM user_audit_log ORDER BY action_time DESC LIMIT 1;

输出示例:
+—-+———+———+———————+————-+————+
| id | user_id | action | action_time | ip_address | user_agent |
+—-+———+———+———————+————-+————+
| 1 | 1502 | CREATE | 2026-04-04 10:35:00 | 123 | SYSTEM |
+—-+———+———+———————+————-+————+
1 row in set (0.00 sec)

4. 级联更新触发器
DELIMITER //

CREATE TRIGGER after_order_status_update
AFTER UPDATE ON orders
FOR EACH ROW
BEGIN
IF OLD.status != NEW.status AND NEW.status = 3 THEN
UPDATE user_statistics
SET completed_orders = completed_orders + 1,
total_amount = total_amount + NEW.amount
WHERE user_id = NEW.user_id;
END IF;
END //

DELIMITER ;

输出示例:
Query OK, 0 rows affected (0.01 sec)

5. 测试级联更新
UPDATE orders SET status = 3 WHERE id = 1;

输出示例:
Query OK, 1 row affected (0.01 sec)

6. 查看用户统计
SELECT * FROM user_statistics WHERE user_id = 1;

输出示例:
+—-+———+——————+————–+
| id | user_id | completed_orders | total_amount |
+—-+———+——————+————–+
| 1 | 1 | 51 | 5100.00 |
+—-+———+——————+————–+
1 row in set (0.00 sec)

Part04-生产案例与实战讲解

4.1 BEFORE vs AFTER

# 触发时机对比

1. BEFORE触发器特点
– 可以修改数据
– 在约束检查前执行
– 可以阻止操作
– 适合数据验证

2. AFTER触发器特点
– 不能修改数据
– 在约束检查后执行
– 操作已提交
– 适合审计日志

3. 使用场景对比
BEFORE触发器适用场景:
– 数据验证
– 数据预处理
– 自动填充字段
– 业务规则检查

AFTER触发器适用场景:
– 审计日志
– 数据同步
– 统计更新
– 通知发送

Part05-风哥经验总结与分享

5.1 触发器执行顺序

# 触发器执行顺序

1. 同一表上的触发器
– 按创建时间顺序执行
– 同一类型触发器按创建顺序
– BEFORE触发器在AFTER触发器之前

2. 创建测试触发器
DELIMITER //

CREATE TRIGGER test_order_1
BEFORE INSERT ON orders
FOR EACH ROW
BEGIN
INSERT INTO trigger_test (trigger_name, execution_time)
VALUES (‘test_order_1’, NOW());
END //

CREATE TRIGGER test_order_2
BEFORE INSERT ON orders
FOR EACH ROW
BEGIN
INSERT INTO trigger_test (trigger_name, execution_time)
VALUES (‘test_order_2’, NOW());
END //

CREATE TRIGGER test_order_3
AFTER INSERT ON orders
FOR EACH ROW
BEGIN
INSERT INTO trigger_test (trigger_name, execution_time)
VALUES (‘test_order_3’, NOW());
END //

DELIMITER ;

输出示例:
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)

3. 测试执行顺序
INSERT INTO orders (user_id, amount) VALUES (1, 100.00);

输出示例:
Query OK, 1 row affected (0.01 sec)

4. 查看执行顺序
SELECT trigger_name, execution_time
FROM trigger_test
ORDER BY execution_time;

输出示例:
+—————+———————+
| trigger_name | execution_time |
+—————+———————+
| test_order_1 | 2026-04-04 10:40:00 |
| test_order_2 | 2026-04-04 10:40:00 |
| test_order_3 | 2026-04-04 10:40:00 |
+—————+———————+
3 rows in set (0.00 sec)

6. 最佳实践

6.1 触发时机选择

# 触发时机选择最佳实践

1. 选择BEFORE时机
– 需要修改数据时
– 需要验证数据时
– 需要阻止操作时
– 需要预处理数据时

2. 选择AFTER时机
– 需要记录日志时
– 需要同步数据时
– 需要更新统计时
– 需要发送通知时

3. 避免的问题
– 避免触发器相互调用
– 避免触发器嵌套过深
– 避免在触发器中执行耗时操作
– 避免触发器逻辑过于复杂

4. 性能考虑
– 触发器会增加操作延迟
– 批量操作时影响更大
– 考虑使用应用层逻辑替代
– 定期评估触发器必要性

GF-MySQL数据库培训文档系列

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息