在MySQL触发器的使用过程中,当我们需要对数据更新、删除操作前的原始记录进行读取或处理时,OLD关键字是核心的访问标识,它可以直接指向触发事件对应的旧数据行,让开发者能够便捷获取修改或删除前的数据内容。

OLD关键字的基本说明
OLD是MySQL触发器内置的临时记录变量,它仅在UPDATE触发器和DELETE触发器中有效,在INSERT触发器中无法使用,因为插入操作不存在旧数据。OLD变量的结构与被触发表的字段结构完全一致,我们可以通过OLD.字段名的方式获取对应字段的旧值。
OLD的适用触发事件
- UPDATE事件:OLD指向更新前的原记录,NEW指向更新后的新记录
- DELETE事件:OLD指向即将被删除的原记录,该事件下没有NEW变量
- INSERT事件:不存在旧数据,因此OLD变量不可用,使用该变量会直接报错
OLD关键字的使用场景
OLD关键字常见的使用场景包括数据变更审计、旧数据备份、变更前后数据对比校验等。比如我们需要在用户表的数据被修改或删除时,把旧数据同步到审计表中,就可以通过OLD关键字获取对应的原始数据。
具体使用示例
场景1:UPDATE触发器中获取旧数据
假设我们有一个用户表user_info,现在需要创建一个触发器,当用户表的年龄字段被更新时,把更新前的年龄记录到审计表user_audit中。
首先创建两张表:
-- 用户表
CREATE TABLE user_info (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
age INT NOT NULL,
update_time DATETIME
);
-- 审计表,用于记录年龄变更前的旧值
CREATE TABLE user_audit (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
old_age INT NOT NULL,
change_time DATETIME NOT NULL
);
创建UPDATE触发器的代码如下:
DELIMITER //
CREATE TRIGGER before_user_update
BEFORE UPDATE ON user_info
FOR EACH ROW
BEGIN
-- 通过OLD.age获取更新前的年龄值
INSERT INTO user_audit (user_id, old_age, change_time)
VALUES (OLD.id, OLD.age, NOW());
END //
DELIMITER ;
当我们执行更新操作时,就可以看到旧数据被记录到审计表中:
-- 插入测试数据
INSERT INTO user_info (username, age, update_time) VALUES ('张三', 20, NOW());
-- 更新年龄
UPDATE user_info SET age = 25 WHERE id = 1;
-- 查看审计表数据,会看到old_age为20
SELECT * FROM user_audit;
场景2:DELETE触发器中获取旧数据
当我们需要删除用户数据时,把被删除的用户旧数据备份到删除备份表user_delete_backup中,对应的触发器实现如下:
首先创建备份表:
CREATE TABLE user_delete_backup (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
username VARCHAR(50) NOT NULL,
age INT NOT NULL,
delete_time DATETIME NOT NULL
);
创建DELETE触发器的代码:
DELIMITER //
CREATE TRIGGER before_user_delete
BEFORE DELETE ON user_info
FOR EACH ROW
BEGIN
-- 通过OLD获取被删除记录的所有旧值
INSERT INTO user_delete_backup (user_id, username, age, delete_time)
VALUES (OLD.id, OLD.username, OLD.age, NOW());
END //
DELIMITER ;
执行删除操作后,备份表会记录被删除用户的完整旧数据:
-- 删除用户 DELETE FROM user_info WHERE id = 1; -- 查看备份表,会看到id为1的用户完整旧数据 SELECT * FROM user_delete_backup;
使用OLD关键字的注意事项
- OLD关键字是只读的,不能在触发器中修改OLD的字段值,尝试修改会直接抛出错误
- 仅在行级触发器(FOR EACH ROW)中可以使用OLD关键字,语句级触发器无法使用
- 如果触发事件中不存在旧数据(比如INSERT事件),使用OLD会报"Unknown column 'OLD.id' in 'field list'"类的错误
- OLD获取的旧值是触发事件发生前的实时数据,不受后续事务回滚的影响,即使事务回滚,触发器中基于OLD的操作已经执行
注意:如果需要在触发器中同时获取新旧数据对比,UPDATE事件下可以结合NEW关键字使用,比如判断年龄是否从小于18变更为大于等于18,就可以通过OLD.age和NEW.age做对比实现。