Showing posts with label Oracle XE Trigger PL SQL Package Auditing FGA Fine Grained. Show all posts
Showing posts with label Oracle XE Trigger PL SQL Package Auditing FGA Fine Grained. Show all posts

Friday, March 6, 2009

Fine Grained Auditing for Oracle XE

Oracle XE does not have FGA (Fine Grained Auditing).
So I had to implement a package and a trigger in order to keep a fine grained record of what data and what column and on what table was the data added,deleted or inserted.
I received quite a bit of help from the Oracle Forum.
I have created a table called "audit_logs" to store the records of inserts,deletes and updates.




Below is the SQL structure for the "audit_logs" table.
CREATE TABLE  "AUDIT_LOGS" 
( "TABLENAME" VARCHAR2(4000),
"COLUMNNAME" VARCHAR2(4000),
"USERNAME" VARCHAR2(4000),
"OLDVAL" VARCHAR2(4000),
"NEWVAL" VARCHAR2(4000),
"AUDITDATE" TIMESTAMP (6)
)
/


Below is the code for the "auditpkg" package.


create or replace package auditpkg AS -- package spec
procedure auditproc( p_tablename varchar2, p_columnname varchar2,
p_oldval varchar2, p_newval varchar2 );
procedure auditproc( p_tablename varchar2, p_columnname varchar2,
p_oldval number, p_newval number );
procedure auditproc( p_tablename varchar2, p_columnname varchar2,
p_oldval date, p_newval date );
end auditpkg;

/

SHOW ERRORS

create or replace package body auditpkg AS -- package body
procedure auditproc
( p_tablename varchar2, p_columnname varchar2, p_oldval varchar2, p_newval varchar2 )
IS
BEGIN
if (p_oldval is null and p_newval is not null)
or (p_oldval is not null and p_newval is null)
or (p_oldval != p_newval)
then
insert into audit_logs( tablename, columnname, username, oldval, newval, auditdate )
values (p_tablename, p_columnname, USER, p_oldval, p_newval, SYSDATE );
end if;
END auditproc;

procedure auditproc
( p_tablename varchar2, p_columnname varchar2, p_oldval number, p_newval number )
IS
BEGIN
if (p_oldval is null and p_newval is not null)
or (p_oldval is not null and p_newval is null)
or (p_oldval != p_newval)
then
insert into audit_logs( tablename, columnname, username, oldval, newval, auditdate )
values (p_tablename, p_columnname, USER, p_oldval, p_newval, SYSDATE );
end if;
END auditproc;

procedure auditproc
( p_tablename varchar2, p_columnname varchar2, p_oldval date, p_newval date )
IS
BEGIN
if (p_oldval is null and p_newval is not null)
or (p_oldval is not null and p_newval is null)
or (p_oldval != p_newval)
then
insert into audit_logs( tablename, columnname, username, oldval, newval, auditdate )
values (p_tablename, p_columnname, USER, p_oldval, p_newval, SYSDATE );
end if;
END auditproc;

END auditpkg;

/
SHOW ERRORS



Below is the code for the "audit_test_audit_trig" trigger
There must be one trigger for each table, each with its own unique trigger name of course.
In the case below, the trigger is for a table called "audit_test"
create or replace trigger audit_test_audit_trig
after insert or update or delete on audit_test
for each row
begin
auditpkg.auditproc( 'AUDIT_TEST', 'COL1', :old.col1, :new.col1 );
auditpkg.auditproc( 'AUDIT_TEST', 'COL2', :old.col2, :new.col2 );
auditpkg.auditproc( 'AUDIT_TEST', 'COL3', :old.col3, :new.col3 );
end;