怎样在SQL触发器中捕获被修改数据的修改前后完整差量

夜磊君_2886

夜磊君_2886

2026-11-01

396人浏览

原创

SQL Server中AFTER UPDATE触发器通过deleted和inserted逻辑表获取新旧数据,需用主键或唯一键显式JOIN;MySQL用OLD/NEW字段;PostgreSQL推荐jsonb差量;均需注意NULL比较、LOB字段及性能问题。

怎样在sql触发器中捕获被修改数据的修改前后完整差量

SQL Server 的 AFTER UPDATE 触发器中如何拿到修改前后的完整行数据

SQL Server 是少数原生支持在触发器中直接访问新旧数据的主流数据库。关键在于使用 deleted 和 inserted 两个临时逻辑表:deleted 包含更新前的原始行(对 UPDATE 和 DELETE 有效),inserted 包含更新后的新行(对 INSERT 和 UPDATE 有效)。它们结构与原表一致,且按主键/唯一约束隐式关联——但注意:没有内置行级顺序保证,必须用主键或唯一列显式 JOIN。

常见错误是直接 SELECT * FROM deleted,结果发现多行时无法对应到 inserted 中哪一行。正确做法是:

  • 始终基于主键(如 id)或业务唯一键(如 order_no)做 INNER JOIN,例如:
    SELECT d.id, d.name AS old_name, i.name AS new_name, d.status AS old_status, i.status AS new_status FROM deleted d INNER JOIN inserted i ON d.id = i.id
  • 如果表无主键,必须先确认存在能唯一标识行的列组合,否则差量不可靠
  • deleted 和 inserted 在单条 UPDATE 语句影响多行时,各自都可能有多行;不能假设只有一行

MySQL 的 BEFORE UPDATE 触发器里怎么记录“修改前”和“修改后”

MySQL 不提供 deleted/inserted 表。在 BEFORE UPDATE 触发器中,你可以读取 OLD.字段名(修改前值)和 NEW.字段名(即将写入的新值),这是唯一可靠方式。但注意:AFTER UPDATE 触发器中 OLD 和 NEW 同样可用,只是时机不同——BEFORE 可修改 NEW 值,AFTER 则不能。

要生成完整差量,需手动拼字段。例如:

INSERT INTO audit_log (table_name, row_id, field_name, old_value, new_value, updated_at) VALUES
('users', OLD.id, 'email', OLD.email, NEW.email, NOW()),
('users', OLD.id, 'status', OLD.status, NEW.status, NOW());
  • 必须为每个需要审计的字段写一行 INSERT,无法用 * 或动态列名
  • 字段类型影响可比性:比如 DATETIME 和 TIMESTAMP 在时区处理上可能表现不一致,建议统一转为字符串再比较
  • OLD 和 NEW 中的 NULL 值需用 IS NULL 判断,不能用 = NULL

PostgreSQL 的 FOR EACH ROW 触发器中如何安全提取变更字段

PostgreSQL 使用 OLD 和 NEW 记录(类似 MySQL),但更灵活:支持在触发器函数中用 hstore 或 jsonb 差量化整行。最简方案是用 jsonb_diff(需 jsonb 类型支持)或手写字段级对比。

推荐用 jsonb 提取差量,避免漏字段:

SELECT jsonb_each_text(NEW::jsonb - OLD::jsonb) AS diff;
  • 该表达式返回所有被修改字段的 (key, value) 对,其中 value 是新值;未变字段自动被减掉
  • 但 OLD 或 NEW 含有 jsonb、数组、几何类型等时,::jsonb 强转可能失败,需提前过滤或封装异常处理
  • 若只要变化字段名列表,可用:(SELECT array_agg(key) FROM jsonb_each_text(NEW::jsonb - OLD::jsonb))

跨数据库通用陷阱:NULL、LOB 字段和性能隐患

所有数据库在差量捕获中都会遇到三类典型问题:NULL 值比较失效、大文本/二进制字段(LOB)导致触发器延迟、以及高并发下日志表写入成为瓶颈。

  • NULL 值永远不等于 NULL,所以 OLD.col != NEW.col 在任一为 NULL 时恒为 FALSE;必须写成 (OLD.col IS DISTINCT FROM NEW.col)(PostgreSQL)或 ISNULL(OLD.col,'') != ISNULL(NEW.col,'')(SQL Server)
  • MySQL 中 TEXT/BLOB 字段在触发器中不可直接用于 OLD/NEW 比较,会报错;应改用长度判断或跳过审计
  • 审计日志表务必建好主键和按时间分区;否则千万级日志后,INSERT 触发器本身会拖慢主表 DML 性能

差量不是越全越好——真正需要追踪的字段往往只有 3~5 个。先明确业务审计范围,再决定是否全量捕获,否则维护成本远高于收益。

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

4683

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

971

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

1229

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

6681

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

3423

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

6660

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

9201

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1250

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1092

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 134.1万人学习