2013-02-05 37 views
6

我有一个120列的表。我需要设置审计跟踪,如果更改了任何列,就会记录它。因为它是现在,我想我必须建立与条件是这样的一个触发每列:MySQL更新触发器 - 找到更改的列?

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

这将需要进行120次......虽然我已经接受了这种方式20年以前,今天我拒绝相信自动化这样一个简单的程序自动找到更改的列是不可能的。

这是我迄今发现:

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

我正在考虑使用BEFORE和AFTER触发器与临时表和变量一起使用,这可能会解决问题,但是又需要动态SQL。我觉得我陷入了死胡同。

有没有解决方案呢?

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

更新:我发现2个可能的解决方案。然而他们都不看不够清楚对我说:使用活动作为一种解决方法结合使用触发器使用动态SQL workaround

  • 。我不得不承认,我不太明白,这是否意味着EVENT无论如何都会每秒发射一次?
  • This article表示只要使用临时表就可以在触发器内使用动态SQL。这仍然使用动态SQL,所以我不太明白。
+0

你检查这与[在Postgres的会话信息函数为您的最后一个问题](http://stackoverflow.com/questions/8759595/within-a-trigger-function-how-to-get-which-fields-are-being-updated ) – bonCodigo

+0

@bonCodigo谢谢,显然PostgreSQL在这种情况下更加灵活。 – Caballero

回答

1

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

+2

感谢您的回答,但是我选择使用触发器的唯一原因是我不必涉及PHP - 如果我选择使用PHP实现此功能,则不会存在此问题。我有一个庞大的系统已经在PHP编码,如果我不得不在那里执行代码审计这将是自杀。 – Caballero

0

我通过创建一个影子表为一个项目做了这个。如果你不处理数以百万计的更新,当用户登录这可能工作

  • ,SET @user_id = {登录的用户ID}
  • 在表上创建一个触发器之前更新复制的行将其修改为具有相同结构的影子表(注意,影子表中不能包含主键,也不能具有唯一键)
  • 向影子表(modified_by,modified_on)添加其他列
  • 创建一个小型php脚本显示列之间的差异 - 这种方式你不touvh现有的PHP代码库
  • 如果你正在处理大量的更新,并希望保持影子表小,一个cron可以写入解析影子表,并确定哪些列发生变化,只是这个信息存储到另一个表