I want to make an history on an Oracle DB about all the DDL operations which are executed by the time.
I have created a TABLE
and a DDL TRIGGER
for do that, in this way:
CREATE TABLE AUDIT_DDL (
D DATE,
OSUSER VARCHAR2(255),
CURRENT_USER VARCHAR2(255),
HOST VARCHAR2(255),
TERMINAL VARCHAR2(255),
OWNER VARCHAR2(30),
TYPE VARCHAR2(30),
NAME VARCHAR2(30),
SYSEVENT VARCHAR2(30));
--/
CREATE OR REPLACE TRIGGER AUDIT_DDL_TRG AFTER DDL ON SCHEMA
BEGIN
IF (ORA_SYSEVENT='TRUNCATE')
THEN
NULL;
ELSE
INSERT INTO AUDIT_DDL(D, OSUSER,CURRENT_USER,HOST,TERMINAL,OWNER,TYPE,NAME,SYSEVENT)
VALUES(
SYSDATE,
SYS_CONTEXT('USERENV','OS_USER') ,
SYS_CONTEXT('USERENV','CURRENT_USER') ,
SYS_CONTEXT('USERENV','HOST') ,
SYS_CONTEXT('USERENV','TERMINAL') ,
ORA_DICT_OBJ_OWNER,
ORA_DICT_OBJ_TYPE,
ORA_DICT_OBJ_NAME,
ORA_SYSEVENT
);
END IF;
END;
/
This works perfectly: after each DDL statement, I have a new row in the AUDIT_DDL table.
But I still don't have any information about the exact kind of operation has been made.
For example, the following two statements will produce the same ALTER
SYSEVENT in the AUDIT_DDL table:
ALTER TABLE MYTABLE RENAME COLUMN TEMP TO NEWTEMP;
ALTER TABLE MYTABLE DROP COLUMN NEWTEMP;
So, in this way, I can't know what operation has been made rather than a generic ALTER TABLE
, and I can't even know if the column TEMP has been renamed or dropped from the table MYTABLE!
My question is: how can I retrieve some more information about the event has occurred after the DDL execution (object involved, details, etc...)?
check the below:
drop the trigger AUDIT_DDL_TRG
drop trigger AUDIT_DDL_TRG
create a new column
alter table AUDIT_DDL add statements varchar2(1000);
run the trigger again
CREATE OR REPLACE TRIGGER AUDIT_DDL_TRG
AFTER DDL ON SCHEMA
DECLARE
sql_text ora_name_list_t;
v_stmt VARCHAR2(2000);
n PLS_INTEGER;
BEGIN
n := ora_sql_txt(sql_text);
FOR i IN 1 .. n LOOP
v_stmt := v_stmt || sql_text(i);
END LOOP;
v_stmt :=regexp_replace(v_stmt,
'rename[[:space:]]+.*[[:space:]]+to[[:space:]]+([a-z0-9_]+)',
'\1',
1,
1,
'i');
IF (ORA_SYSEVENT = 'TRUNCATE') THEN
NULL;
ELSE
INSERT INTO AUDIT_DDL
(D,
OSUSER,
CURRENT_USER,
HOST,
TERMINAL,
OWNER,
TYPE,
NAME,
SYSEVENT,
statements)
VALUES
(SYSDATE,
SYS_CONTEXT('USERENV', 'OS_USER'),
SYS_CONTEXT('USERENV', 'CURRENT_USER'),
SYS_CONTEXT('USERENV', 'HOST'),
SYS_CONTEXT('USERENV', 'TERMINAL'),
ORA_DICT_OBJ_OWNER,
ORA_DICT_OBJ_TYPE,
ORA_DICT_OBJ_NAME,
ORA_SYSEVENT,
v_stmt);
END IF;
END;
/
do some alters, and youll see the statement