Oracle Audit表使用触发器

时间:2017-07-09 18:33:36

标签: oracle plsql triggers auditing audit-trail

我需要在Oracle 11g中创建一个用于审核表的触发器。我有一个16列的表需要审核。

对于表中的每个新插入,我需要在审计表中为每个插入的列添加一个条目,即在此方案中,将在审计表中插入16行。

对于每次更新,假设我更新了第1列和第2列,那么它将在审计中创建两条记录,其旧值和新值。审计表的结构将是:

 id        
 mod_col_name 
 OLD VALUE 
 NEW VALUE  
 upd_time 
 mod_user_id

我的方法:

create or replace trigger my_trigger
after update or insert on temp12
for each row
declare

  TYPE tab_col_nt IS table of varchar2(30);

  v_tab_col_nt tab_col_nt;

begin

    v_tab_col_nt := tab_col_nt('id','name','salary'); --in example i have given only 3 column name

    for r in v_tab_col_nt.first..v_tab_col_nt.last

    loop

        if updating(v_tab_col_nt(r)) then

            insert into audit_table values (
                id_seq.nextval, v_tab_col_nt(r), :old.v_tab_col_nt(r),
                :new.v_tab_col_nt(r), sysdate, user
             ); --here :old & :new syntex is not working
        end if;

        if inserting then
            insert into audit_table values (
               id_seq.nextval, v_tab_col_nt(r), null, 
               :new.v_tab_col_nt(r), sysdate, user);
        end if;

    end loop;
end;

我的担心:

  1. 此处:old.v_tab_col_nt(r),:new.v_tab_col_nt(r)无法正常工作

  2. 如何跟踪用户登录GUI的用户ID(点网是前端)。

  3. 我希望动态编写此触发器。

1 个答案:

答案 0 :(得分:1)

:old.v_tab_col_nt(r):new.v_tab_col_nt(r)无效的原因是因为:old:new仅适用于旧的和新的(duh!...)值的引用表中受影响的列,而不是触发器内声明的用户定义类型。

您实际需要的值包括::old.<name of column1>:new.<name of column1>

因此,根据您的要求,触发器必须如下所示:

create or replace trigger my_trigger
after insert or update on temp12
for each row
referencing old as old new as new
begin

    /*When-Insert block. 1 record for each column in audit*/
    if (INSERTING) then -- 
        insert into audit_table values (id_seq.nextval, '<name of column1>', :old.<name of column1>, :new.<name of column1>, sysdate, user);
        insert into audit_table values (id_seq.nextval, '<name of column2>', :old.<name of column2>, :new.<name of column2>, sysdate, user);
        insert into audit_table values (id_seq.nextval, '<name of column3>', :old.<name of column3>, :new.<name of column3>, sysdate, user);
         .
         . --(same for every column)
         .
        insert into audit_table values (id_seq.nextval, '<name of column16>', :old.<name of column16>, :new.<name of column16>, sysdate, user);
    end if;
    /*end of When-Insert block*/

    /*When-Update block. A new record in audit just for the updated column(s) */
    if (UPDATING ( '<name of column1>' )) then --col 1
        insert into audit_table values (id_seq.nextval, '<name of column1>', :old.<name of column1>, :new.<name of column1>, sysdate, user);
    end if;
    if (UPDATING ( '<name of column2>' )) then --col 2
        insert into audit_table values (id_seq.nextval, '<name of column2>', :old.<name of column2>, :new.<name of column2>, sysdate, user);
    end if;
    if (UPDATING ( '<name of column3>' )) then --col 3
        insert into audit_table values (id_seq.nextval, '<name of column3>', :old.<name of column3>, :new.<name of column3>, sysdate, user);
    end if;
     . 
     . --(same for every column)
     .
    if (UPDATING ( '<name of column16>' )) then --col 16
        insert into audit_table values (id_seq.nextval, '<name of column16>', :old.<name of column16>, :new.<name of column16>, sysdate, user);
    end if;
    /*end of When-Update block*/

end;

现在关于将已登录用户跟踪到您的应用程序中有两个注意事项:

  1. 如果您的整个应用程序在数据库级别实现了所有用户, 这是每个登录个人的ORACLE用户,如果是这样,那么 将执行每个PL / SQL块或DDL中的保留字“USER” 每次都检索该用户名。

  2. 另一方面,如果您的应用程序决定管理用户     他们自己,通过创建自定义用户控件,然后该值必须     可以通过参数传递(在命名PL / SQL块的情况下)或     在每个表中包含一个(NOT NULL)列(至少每个表     您希望监视用户活动),以便每个INSERT语句都是     被迫发送该信息,你可以使用里面的:new.<name of user monitor column>来阅读它     您的触发器代码,或者您可以使用类似

  3. 的内容

    IF (:new.< name of user monitor column > is null) then raise_application_error(-20001, 'User must be specified'). END IF;

    愿力量与你同在。