MySQL更新触发器 - 查找更改的列?

时间:2013-02-05 09:17:17

标签: mysql triggers

我有一个包含120列的表格。我需要设置审计跟踪,如果已更改,则会记录任何列。就像现在一样,我想我必须为每一列设置一个具有类似条件的触发器:

IF(NEW.columnName != OLD.columnName)
THEN //log the old value

这需要完成120次......虽然我会在20年前接受这种方法,但今天我拒绝相信自动执行这样一个简单的程序自动找到更改的列。

这是我到目前为止所发现的:

  • NEW和OLD都不是一个表,它是一种语言结构,因此你不能做“现在选择。*”或类似的东西。
  • 触发器中不允许使用动态SQL(这可以解决问题)。
  • 触发器中不允许使用动态SQL的程序(严重的是,Oracle,看起来你无论如何都很难禁用此功能)。

我正在考虑将BEFORE和AFTER触发器与可能解决问题的临时表和变量结合使用,但是再次需要动态SQL。我觉得我走到了尽头。

根本没有解决方案吗?

一个附带问题:这在PostgreSQL中是否可行?

更新:我找到了2个可能的解决方案,但它们对我来说都不够清晰:

  • 使用EVENTS作为解决方法,将触发器与动态SQL workaround结合使用。我不得不承认,我不太明白,这是否意味着无论如何,EVENT每秒都会开火?
  • This article表示只要与临时表一起使用,就可以在触发器内部使用动态SQL。那仍然是使用动态SQL,所以我不太明白。

2 个答案:

答案 0 :(得分:1)

有趣的是,几年前我在实施基于动态触发器的审计日志时遇到了同样的问题。我想出的解决方案是简单地生成SQL触发器代码,然后可以(自动)应用它来替换旧的触发器定义。如果内存服务,我创建了几个由PHP脚本处理的SQL模板,而PHP脚本又根据“SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE ...”输出完整的触发器定义。是的,触发器代码很大,但它有效!希望有点帮助=)

答案 1 :(得分:0)

我通过创建影子表为其中一个项目做了这个。如果您没有处理数百万次更新,这可能会有效

  • 当用户登录时,SET @user_id = {登录用户ID}
  • 在更新之前在表上创建一个触发器,将要修改的行复制到具有相同结构的影子表(请注意,影子表中不能有主键,也不能使用唯一键)
  • 将其他列添加到影子表(modified_by,modified_on)
  • 创建一个小的PHP脚本来显示列之间的差异 - 这样你就不会破坏现有的php代码库
  • 如果您正在处理大量更新并希望保持影子表较小,可以编写一个cron来解析影子表并确定哪个列已更改并仅将此信息存储到另一个表中