在 Oracle 中审计 DML 更改

Posted

技术标签:

【中文标题】在 Oracle 中审计 DML 更改【英文标题】:Auditing DML changes in Oracle 【发布时间】:2017-01-26 19:22:41 【问题描述】:

我想在一个名为 Tables_History 的表中记录所有表的更改,每个表都有一个触发器,并且不根据列的类型明确地处理列名。因为我有 50 个属于不同项目的表。许多开发人员可能会更改表的结构。所以我不能明确地处理列名。这是 Tables_History 的定义:

create table Tables_History
(
  user_id        VARCHAR2(10) not null,
  change_date    DATE not null,
  table_name     VARCHAR2(100) not null,
  column_name    VARCHAR2(100) not null,
  primary_key_id INTEGER not null,
  old_number     NUMBER,
  new_number     NUMBER,
  old_string     VARCHAR2(900),
  new_string     VARCHAR2(900),
  old_date       DATE,
  new_date       DATE,
  ...
  .
);

如果有任何方法可以访问触发器中的 :new 列值,请通过将列名作为参数而不是标准方式 (:new.column_name) 传递。像这样(:new['column_name'])。 这是我对一个表的理想触发器(然后我可以将此触发器复制+粘贴到其他表并仅更改几个参数:-D):

create or replace trigger Audit_TableName
  before update on TableName
  for each row
declare
  v_query  varchar(32767);
  UserCode varchar(10);
begin

  SELECT sys_context('USERENV', 'CLIENT_IDENTIFIER')
  INTO UserCode
  FROM DUAL;             

  FOR getrec IN (SELECT column_name, data_type
                   FROM all_tab_columns
                  WHERE table_name = 'TableName'
                    AND owner = 'MEHRAN'
                    AND data_type <> 'BLOB') LOOP
    if Updating(getrec.column_name) then
      if getrec.data_type = 'NUMBER' then
        v_query := 'insert into Tables_History(user_id,change_date,table_name,column_name,primary_key_id,,,OLD_NUMBER, NEW_NUMBER)'
           ||'values('..,..,..,..||:old[getrec.column_name]||','||:new[getrec.column_name]||')';
      else if getrec.data_type = 'VARCHAR2' then
        v_query := 'insert into Tables_History(...,...,... OLD_VARCHAR, NEW_VARCHAR)'
           ||'values(...,...,..'||:old[getrec.column_name]||','||:new[getrec.column_name]||')';
      ...
      .
      .  
      end if;
      EXECUTE IMMEDIATE v_query;
    end if;
  END LOOP;

end Audit_TableName;

【问题讨论】:

尝试打印你构建的动态查询;这会给你一些提示来编辑你的代码 我认为使用触发器是不可能的。即使你让它动态化,我怀疑它会起作用。顺便说一句,你为什么要这样做。 在这方面提供更多细节。告诉我们您希望触发器看起来如何相似?分享您需要的示例代码或输出。 【参考方案1】:

你不能这样做。您可以编写存储过程来生成静态引用新/旧值的触发器:https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:59412348055

【讨论】:

【参考方案2】:

我认为(没有第一手经验)Flashback Data Archive 可以做你想做的事,如果你使用的是 Oracle11 或更高版本。

【讨论】:

以上是关于在 Oracle 中审计 DML 更改的主要内容,如果未能解决你的问题,请参考以下文章

特定表的 Oracle 11g 审计跟踪

Oracle 中的审计

如何筛选 Azure 审核

ORACLE 回滚和触发

oracle中如何更改一个表的一个字段属性(名称,类型)

从审计表中查找更改