【问题标题】:Select all tables where data was created in the last 10 minutes选择过去 10 分钟内创建数据的所有表
【发布时间】:2017-08-07 21:09:10
【问题描述】:

在 Oracle 中,我可以使用

获取过去 10 分钟内创建的数据
SELECT * FROM MY_TABLE WHERE  created_dt > sysdate - interval '10' minute and created_dt < sysdate;

但是,我需要找出过去 10 分钟内创建数据的所有表。

【问题讨论】:

标签: sql oracle


【解决方案1】:

好的,据我了解,您需要在过去 10 分钟内添加/创建数据的所有表的列表。

这是我的方法:

  1. 首先获取包含该列“created_Dt”的所有表的列表。

  2. 遍历所有这些表并检查是否在过去 10 分钟内添加了数据。

& 然后显示添加到这些表中的每一个的行数。

SET SERVEROUTPUT ON;
DECLARE

CURSOR ALL_TABLES_NAME IS
SELECT * FROM ALL_TABLES "ALL"
WHERE EXISTS(SELECT 1 FROM all_cons_columns WHERE table_name = "ALL".TABLE_NAME AND COLUMN_NAME=UPPER('created_dt'));

ALL_TABLES_NAME_REC ALL_TABLES_NAME%rowtype;

row_count number;

BEGIN

OPEN ALL_TABLES_NAME;

LOOP

FETCH ALL_TABLES_NAME INTO ALL_TABLES_NAME_REC;
EXIT WHEN ALL_TABLES_NAME%notfound;

EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ' || ALL_TABLES_NAME_REC.TABLE_NAME || ' WHERE created_dt > (SYSDATE-10/24/60)' INTO row_count;

DBMS_OUTPUT.PUT_LINE('Table '|| ALL_TABLES_NAME_REC.table_name || ' has been updated with '|| row_count || ' new rows');


END LOOP;

CLOSE ALL_TABLES_NAME;

END;
/

【讨论】:

    【解决方案2】:

    一种方法是启用闪回,然后您可以这样做:

    SELECT * FROM table1
    MINUS
    SELECT * FROM table1 AS OF TIMESTAMP SYSTIMESTAMP - INTERVAL '10' MINUTE;
    

    您可以查询数据字典以查找所有表的列表,并为每个表构建一个动态查询,然后使用EXECUTE IMMEDIATE 循环遍历所有表。

    如果您没有启用闪回,那么您需要在每个表上都有一个 created_dt 列(或等效列)。

    【讨论】:

      【解决方案3】:

      如果您的表有MONITORING,一种方法是只使用数据字典来查看表修改。如果MONITORING 处于打开状态,则以下方法应让您查看在给定时间段内哪些表已收到INSERTs(或UPDATEs 或DELETEs,如果需要)。

      以下方法的缺点是必须等待 10 分钟才能检查已创建的内容,但它不需要表具有任何特定列。

      更新:根据 Ikrom 的评论,最初的答案存在缺陷,只检查了一次数据字典。此答案已更新为检查两次以检测更改。

      此方法将记录基线表修改计数,然后在 10 分钟后检查是否有任何更改。它使用两个工作表,一个用于参考ALL_TAB_MODIFICATIONS_REF,一个用于查看 10 分钟后修改的表ALL_TAB_MODIFICATIONS_COMPARE

      CREATE GLOBAL TEMPORARY TABLE
        ALL_TAB_MODIFICATIONS_REF
      ON COMMIT PRESERVE ROWS
        AS SELECT * FROM ALL_TAB_MODIFICATIONS WHERE ROWNUM < 0;
      
      CREATE GLOBAL TEMPORARY TABLE
        ALL_TAB_MODIFICATIONS_COMPARE
      ON COMMIT PRESERVE ROWS
        AS SELECT * FROM ALL_TAB_MODIFICATIONS WHERE ROWNUM < 0;
      
      Table created.
      Table created.
      

      创建这些工作表后,可以通过获取初始状态并在 10 分钟后与最终状态进行比较来检测任何更改。运行以下代码块后,可以查询ALL_TAB_MODIFICATIONS_COMPARE 以查看哪些表已被INSERTed。

      BEGIN
        --Flush monitoring info, to get a baseline.
        DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO();
      
        --Capture the initial state.
        INSERT INTO ALL_TAB_MODIFICATIONS_REF
          SELECT * FROM ALL_TAB_MODIFICATIONS;
        COMMIT;
      
        -- Wait ten minutes.
        DBMS_LOCK.SLEEP(600);
      
        --Flush monitoring info, to get a snapshot for comparison.
        DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO();
      
        -- Capture the final state.
        INSERT INTO ALL_TAB_MODIFICATIONS_COMPARE
          SELECT * FROM ALL_TAB_MODIFICATIONS
          WHERE NOT EXISTS(SELECT 1 FROM ALL_TAB_MODIFICATIONS_REF
          WHERE ALL_TAB_MODIFICATIONS_REF.TABLE_OWNER = ALL_TAB_MODIFICATIONS.TABLE_OWNER
                AND ALL_TAB_MODIFICATIONS_REF.TABLE_NAME = ALL_TAB_MODIFICATIONS.TABLE_NAME
                AND ALL_TAB_MODIFICATIONS_REF.INSERTS >= ALL_TAB_MODIFICATIONS.INSERTS);
        COMMIT;
      
      END;
      /
      

      运行块后,检查带有INSERTs 的表:

      SELECT TABLE_NAME FROM ALL_TAB_MODIFICATIONS_COMPARE;
      

      这是一个示例,用于检测一个表在 10 分钟内发生的更改,但排除另一个表,因为它自上次 INSERT 以来已超过 10 分钟:

      创建测试表:

      CREATE TABLE RECENT_DML (THE_DATA NUMBER, DML_TIME TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL); 
      CREATE TABLE NO_RECENT_DML (THE_DATA NUMBER, DML_TIME TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL);
      
      Table created.
      Table created.
      

      并在两个表中添加一些初始测试数据。

      INSERT INTO RECENT_DML (THE_DATA) VALUES (1);
      INSERT INTO NO_RECENT_DML (THE_DATA) VALUES (1);
      COMMIT;
      
      1 row inserted.
      1 row inserted.
      Commit complete.
      

      然后在上面的一个会话中运行上面的监控块,以检测 10 分钟后的变化。

      当块在第一个会话中运行时,在第二个会话中将更多数据添加到仅RECENT_DML

      INSERT INTO RECENT_DML (THE_DATA) VALUES (1);
      COMMIT;
      
      1 row inserted.
      Commit complete.
      

      在第一个会话中块完成后,查询修改的表:

      SELECT TABLE_NAME FROM ALL_TAB_MODIFICATIONS_COMPARE;
      
      TABLE_NAME                    
      RECENT_DML 
      

      【讨论】:

      • 通过运行此BEGIN DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO(); END;,该表将包含此进程的TIMESTAMP,而不是上次DML 时间的表。例如,如果一个表在 1 小时前更新,而您现在执行了flush,那么它将显示当前时间,而不是表中数据被修改的实时时间,或者需要准确地每十分钟运行一次命令。
      • 感谢@Ikrom 提供了一些值得研究的东西。我更新提到了这一点,如果有一个干净的改进,我会进行实验和更新。谢谢
      • @Ikrom 感谢您的反馈。实际上,这种方法需要比较两个点来排除窗口外的记录。答案已更新。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-28
      • 2021-09-25
      • 1970-01-01
      相关资源
      最近更新 更多