简体   繁体   English

触发创建表为 sql

[英]Trigger on the create table as sql

I want to save the SQL create statement as following:我想将 SQL create 语句保存如下:

CREATE TABLE tbl AS 
 SELECT 
  *
 FROM 
  tbl_info; 

Is there a way to save the previous query in a table like this:有没有办法将以前的查询保存在这样的表中:

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

which table_name, query are the columns of this table, i tried to look up for triggers but there is nothing about trigger before or after on create statement, please your help.哪个表名,查询是该表的列,我试图查找触发器,但在创建语句之前或之后没有关于触发器的信息,请您帮忙。

Indeed there is a way of doing this, but it is not recommendable.确实有一种方法可以做到这一点,但不推荐。 Oracle offers out of the box audit capabilities much better than any custom solution you can think of. Oracle 提供开箱即用的审计功能,比您能想到的任何自定义解决方案都要好得多。

Having said that, one option would be to use a DDL TRIGGER .话虽如此,一种选择是使用DDL TRIGGER In the example below you have an audit table to store the create event and a trigger to record them.在下面的示例中,您有一个审计表来存储create事件和一个trigger来记录它们。

Keep in mind that I use ON SCHEMA , so it will only affect the CREATE events for the schema which the trigger belongs to.请记住,我使用ON SCHEMA ,因此它只会影响触发器所属模式的 CREATE 事件。

Base code基本代码

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;
/

Let's check how it works让我们检查一下它是如何工作的

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

As you can see above ( on purpose ), I did several statements ( a create failing, a drop table, and finally a CTAS statement ).正如您在上面看到的(故意的),我做了几个语句(一个创建失败,一个删除表,最后一个CTAS语句)。 However, our event trigger is only looking for the sysevent create, and because it is after ddl on schema , it will only store the data after the command is executed successfully.然而,我们的事件触发器只是在寻找sysevent create,因为它是after ddl on schema ,它只会在命令执行成功后存储数据。

You can store many other properties of the default context sys_context .您可以存储默认上下文sys_context的许多其他属性。

Nevertheless, this has a huge impact in performance and it is not recommendable不过这样对性能影响很大,不推荐

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM