2

我有一个正在使用的现有应用程序,并且客户已经定义了他们希望用于审计日志的表结构。它具有以下列:

storeNo 
timeChanged
user 
tableChanged 
fieldChanged 
BeforeValue 
AfterValue

通常我在每个表上都有简单的审计列,提供 userChanged 和 timeChanged 值。将写入这些表的应用程序是一个 java 应用程序,调用是通过 jdbc 在 oracle 数据库上进行的。我的问题是获得之前/之后值的最佳方法是什么。我讨厌比较对象以查看为填充此表所做的更改,这不会有效。如果在一次更新中更改了多个列,则此新表将具有多个条目。或者有没有办法在oracle中做到这一点?过去其他人做了什么来不仅跟踪变化,而且跟踪变化的价值观?

4

4 回答 4

10

这通常是预言机触发器的用途。每次插入或更新都会触发一个存储过程,该过程可以访问“之前和之后”数据,您可以随意使用这些数据,例如将旧值记录到审计表中。它对应用程序是透明的。

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:59412348055

于 2009-11-09T22:34:38.257 回答
2

“客户已经为审计日志定义了他们想要的表结构”

恐言。

以下是您将如何实现这样的事情:

create or replace trigger emp_bur before insert on emp for each row
begin
    if :new.ename = :old.ename then
        insert_audit_record('EMP', 'ENAME', :old.ename, :new.ename);
    end if;
    if :new.sal = :old.sal then
        insert_audit_record('EMP', 'SAL', :old.sal, :new.sal);
    end if;
    if :new.deptno = :old.deptno then
        insert_audit_record('EMP', 'DEPTNO', :old.deptno, :new.deptno);
    end if;
end;
/

如您所见,它涉及大量重复,但使用构建在数据字典上的代码生成器很容易处理。但这种方法存在更严重的问题。

  1. 它有相当大的开销:涉及十个字段的单个更新将生成十个插入语句。
  2. 当我们必须处理不同的数据类型时,BeforeValue 和 AfterValue 列会出现问题——甚至日期和时间戳也会变得有趣,更不用说 CLOB。
  3. 很难在某个时间点重建记录的状态。我们需要从记录的最早版本开始,逐步应用后续更改。
  4. 这种方法如何处理 INSERT 和 DELETE 语句还不是很明显。

现在,如果客户的基本要求是监视对少数敏感列的更改:EMPLOYEES.SALARY、CREDIT_CARDS.LIMIT 等,那么这些反对意见都不是问题。但是如果要求监视每个表的更改,则“整个记录”方法更好:只需为受 DML 影响的每一行插入一条审计记录。

于 2009-11-10T14:11:41.837 回答
2

如果您使用 Oracle 10g 或更高版本,则可以使用内置的审计功能。您为许可证支付了很多钱,不妨使用它。

在http://www.oracle.com/technology/pub/articles/10gdba/week10_10gdba.html了解更多信息

于 2009-11-10T15:17:48.613 回答
0

我会同上触发器。

如果您必须在应用程序级别执行此操作,那么如果不执行这些步骤,我看不出它是如何实现的:

  1. 开始交易
  2. SELECT FOR UPDATE 要更改的记录
  3. 对于要更改的每个字段,从记录中获取旧值并从程序逻辑中获取新值
  4. 对于要更改的每个字段,编写审核记录
  5. 更新记录
  6. 结束交易

如果有很多这样的东西,我想我会创建一个更新记录函数来进行比较,无论是在通用级别还是每个表的单独函数。

于 2009-11-09T23:08:04.733 回答