【问题标题】:Trigger on the create table as sql在创建表上触发为 sql
【发布时间】:2021-11-24 00:20:01
【问题描述】:

我想将 SQL create 语句保存如下:

CREATE TABLE tbl AS 
 SELECT 
  *
 FROM 
  tbl_info; 

有没有办法将上一个查询保存在这样的表中:

table_name  query
tbl         CREATE TABLE tbl AS SELECT * FROM tbl_info;

which table_name, query 是这个表的列, 我试图查找触发器,但在 create 语句之前或之后没有关于触发器的内容, 请您帮忙。

【问题讨论】:

  • 您是否要保存所有用户发出的sql?或者你只是想保存一个(一个)特定的语句?很难理解你想要做什么。你能提供更多细节吗?
  • @Miguel 是的,所有创建语句都已发布。
  • 您将无法使用触发器来执行此操作,您需要打开数据库跟踪,但会影响性能。或者你可以在一定程度上使用 v$sql。
  • @loyalTurkman,可以通过触发器来完成。请参阅下面的答案。

标签: sql oracle plsql triggers


【解决方案1】:

确实有办法做到这一点,但不推荐。 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 的许多其他属性。

不过,这对性能有很大影响,不推荐

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-03
    • 2018-11-02
    • 2020-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多