确实有办法做到这一点,但不推荐。 Oracle 提供的开箱即用审计功能比您能想到的任何自定义解决方案都要好。
话虽如此,一种选择是使用DDL TRIGGER。在下面的示例中,您有一个审计表来存储 create 事件和一个 trigger 来记录它们。
请记住,我使用ON SCHEMA,因此它只会影响触发器所属架构的 CREATE 事件。
基本代码
CREATE TABLE AUDIT_DDL (
D DATE,
OSUSER VARCHAR2(255),
CURRENT_USER VARCHAR2(255),
SYSEVENT VARCHAR2(30),
STATEMENTS VARCHAR2(1000)
);
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 = 'CREATE')
THEN
INSERT INTO AUDIT_DDL
(D,
OSUSER,
CURRENT_USER,
SYSEVENT,
STATEMENTS)
VALUES
(SYSDATE,
SYS_CONTEXT('USERENV', 'OS_USER'),
SYS_CONTEXT('USERENV', 'CURRENT_USER'),
ORA_SYSEVENT,
v_stmt);
END IF;
END;
/
让我们看看它是如何工作的
sqlplus test1/Oracle_123
SQL*Plus: Release 19.0.0.0.0 - Production on Sun Oct 3 11:13:21 2021
Version 19.6.0.0.0
Copyright (c) 1982, 2019, Oracle. All rights reserved.
Last Successful login time: Wed Sep 22 2021 08:08:57 +02:00
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.6.0.0.0
SQL> create table t1 as select * from all_objects ;
create table t1 as select * from all_objects
*
ERROR at line 1:
ORA-00955: name is already used by an existing object
SQL> drop table t1 purge;
Table dropped.
SQL> create table t1 as select * from all_objects ;
Table created.
SQL> select d,statements from AUDIT_DDL ;
D
---------
STATEMENTS
--------------------------------------------------------------------------------
03-OCT-21
create table t1 as select * from all_objects
正如您在上面看到的(故意),我做了几条语句(创建失败、删除表,最后是CTAS 语句)。但是我们的事件触发器只是寻找sysevent创建,因为是after ddl on schema,所以只会在命令执行成功后才存储数据。
您可以存储默认上下文sys_context 的许多其他属性。
不过,这对性能有很大影响,不推荐