我需要在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;
我的担心:
此处:old.v_tab_col_nt(r),:new.v_tab_col_nt(r)无法正常工作
如何跟踪用户登录GUI的用户ID(点网是前端)。
我希望动态编写此触发器。
答案 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;
现在关于将已登录用户跟踪到您的应用程序中有两个注意事项:
如果您的整个应用程序在数据库级别实现了所有用户, 这是每个登录个人的ORACLE用户,如果是这样,那么 将执行每个PL / SQL块或DDL中的保留字“USER” 每次都检索该用户名。
另一方面,如果您的应用程序决定管理用户
他们自己,通过创建自定义用户控件,然后该值必须
可以通过参数传递(在命名PL / SQL块的情况下)或
在每个表中包含一个(NOT NULL)列(至少每个表
您希望监视用户活动),以便每个INSERT
语句都是
被迫发送该信息,你可以使用里面的:new.<name of user monitor column>
来阅读它
您的触发器代码,或者您可以使用类似
IF (:new.< name of user monitor column > is null) then raise_application_error(-20001, 'User must be specified').
END IF;
愿力量与你同在。