7

我有一张有 120 列的表。我需要设置审计跟踪,如果它被更改,它将记录任何列。就像现在一样,我想我必须为每一列设置一个条件如下的触发器:

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

这需要做 120 次……虽然 20 年前我会接受这种方法,但今天我拒绝相信不可能自动化这样一个简单的过程来自动查找更改的列。

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

  • NEW 和 OLD 都不是表格,它是一种语言结构,因此您不能执行“SELECT NOW.*”或类似的操作。
  • 触发器中不允许使用动态 SQL(这可以解决问题)。
  • 触发器中不允许使用动态 SQL 的过程(说真的,Oracle,看起来您无论如何都非常努力地禁用此功能)。

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

有没有办法解决这个问题?

一个附带问题:这在 PostgreSQL 中可能吗?

更新:我发现了 2 个潜在的解决方案,但它们对我来说都不够清楚:

  • 使用 EVENTS 作为一种变通方法,将触发器与动态 SQL变通方法结合使用。我不得不承认,我不太明白这一点,这是否意味着 EVENT 无论如何都会每秒触发一次?
  • 这篇文章说,只要使用临时表,就可以在触发器中使用动态 SQL。那还是用动态SQL,所以不太明白。
4

2 回答 2

1

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

于 2013-02-06T01:22:28.483 回答
0

我通过创建影子表为其中一个项目做到了这一点。如果您不处理数以百万计的更新,这可能会奏效

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