【问题标题】:Combine results of multiple queries in Oracle Sql在 Oracle Sql 中合并多个查询的结果
【发布时间】:2015-05-21 12:59:11
【问题描述】:

数据库 - Oracle 数据库 10g 版本 10.2.0.4.0 , 使用 Oracle SQL Developer

编辑 抱歉:Query-1 应该是:

SELECT TABLE_NAME FROM USER_TABLES;

之前是SELECT OWNER, TABLE_NAME FROM ALL_TABLES;

输出 1:我拥有的所有表

查询 2: SELECT COUNT(*) FROM MYTABLE_1;

输出 2:特定表中的总行数 MYTABLE_1

查询 3: SELECT MAX(ORA_ROWSCN) FROM MYTABLE_1;

Query-3 的输出是一个数字 (493672033308),在 Query-4 中进一步使用

查询 4: SELECT SCN_TO_TIMESTAMP(493672033308) FROM DUAL;

Output-4 是特定表的最后更新时间MYTABLE_1

如何将所有这些结合起来以获得所有用户表的列表,该列表共有 3 列,列标题为 TABLE_NAME、TOTAL_ROWS、LAST_UPDATE_TIME

EDIT-2:最终查询:

SELECT t.TABLE_NAME , m.TIMESTAMP , t.NUM_ROWS , ((NVL(t.NUM_ROWS,0) + m.INSERTS) - m.DELETES) AS TOT_ROWS FROM USER_TABLES t LEFT OUTER JOIN USER_TAB_MODIFICATIONS m ON t.TABLE_NAME = m.TABLE_NAME ORDER BY t.TABLE_NAME;

感谢 APC、StevieG、鲍勃·迪伦 :)

【问题讨论】:

  • 如何处理从 query-1 返回的所有其他表?
  • 更正了错误。我只需要查看“user_tables”而不是“all_tables”
  • 问题仍然存在......
  • 使用“user_tables”在 Query-1 中返回的表总数为 148。我想要所有 148 的时间戳和计数的详细信息。因此无需担心额外的表。

标签: sql oracle


【解决方案1】:

您想使用数据字典的内容来驱动查询。这只能在过程中使用动态 SQL 来完成。

需要注意的几点:

  1. Oracle 维护 SCN 时间戳映射以支持闪回查询。它只是在支持的 UNDO_RETENTION 期间保留映射。因此,我们只能将 SCN_TO_TIMESTAMP() 用于具有最近活动的表。 Staler 表会抛出 ORA-08181。
  2. 没有行的表没有关联的 SCN。如果我们将 SCN_TO_TIMESTAMP() 传递给 SCN,则 SCN_TO_TIMESTAMP() 会抛出 null。

因此,强大的解决方案非常复杂。这个使用 DBMS_OUTPUT 来显示结果;其他机制可用:

declare
    n pls_integer;
    max_scn number;
    x_scn_too_old exception;
    pragma exception_init(x_scn_too_old ,-08181);
    txt varchar2(30);
begin
    for lrec in ( select table_name from user_tables )
    loop
        execute immediate 
            'select count(*), max(ora_rowscn) from '
                || lrec.table_name
                into n, max_scn;
        dbms_output.put(lrec.table_name
                                ||' count='||to_char(n));
        begin
            if n > 0 then
                select to_char(scn_to_timestamp(max_scn), 'yyyy-mm-dd hh24:mi:ss.ff3')
                into txt
                from dual;
            else
                txt := null;
            end if;
        exception
            when x_scn_too_old then
                txt := ('earlier');
        end;
        dbms_output.put_line(' ts='||txt );
    end loop;
end;
/

有一个纯 SQL 替代方案,使用来自 USER_TABLES 和 USER_TAB_MODIFICATIONS 视图的 NUM_ROWS。此视图由 Oracle 维护以监视表上统计信息的陈旧性。当您使用 10g 时,这将自动发生(在 9i 中,我们必须打开对特定表的监控)。

USER_TAB_MODIFICATIONS 为我们提供了每个表上 DML 活动的数字,这很简洁,因为我们可以将这些数字添加到 NUM_ROWS 以获得准确的总数,这比发出 COUNT() 更有效。

再说几点。

  1. 任何缺少统计信息的表都会有 NUM_ROWS=0。出于这个原因,我在算术列中使用 NVL()
  2. USER_TAB_MODIFICATIONS 仅包含自上次收集统计信息以来已更改的表的数据。一旦我们收集了一个表的统计信息,它就会从那个视图中消失,直到发出更多的 DML。所以,使用外连接。
  3. 请注意,我们只会为具有陈旧统计信息的表提供时间戳。这比上面使用的 SCN_TO_TIMESTAMP 更难预测,因为它取决于您的统计数据收集策略。

原来是这样:

select t.table_name
        , m.timestamp
        , t.num_rows
        , ((nvl(t.num_rows,0) + m.inserts) - m.deletes) as tot_rows
from user_tables t
     left outer join USER_TAB_MODIFICATIONS m
         on t.table_name = m.table_name
order by t.table_name
/

也许最好的解决方案是组合使用 NUM_ROWS 和 USER_TAB_MODIFICATIONS 来避免计数,并且只检查 ORA_ROWSCN 以获取具有新统计信息的表。


请注意,这只是一个问题,因为您没有自己的日志或表格审核。许多地方在其表中添加元数据列以跟踪更改数据(例如 CREATED_ON、CREATED_BY、UPDATED_ON、UPDATED_BY)。

【讨论】:

  • 感谢 APC...tot_rows 专栏很棒 :)
【解决方案2】:

我会这样做:

SELECT a.OWNER, a.TABLE_NAME, a.NUM_ROWS, b.TIMESTAMP
FROM ALL_TABLES a
INNER JOIN DBA_TAB_MODIFICATIONS b ON a.OWNER = b.TABLE_OWNER AND a.TABLE_NAME = b.TABLE_NAME

edit - 这是正确的,除了 NUM_ROWS 可能不完全准确: http://www.dba-oracle.com/t_count_rows_all_tables_in_schema.htm

【讨论】:

  • 我知道 NUM_ROWS 的限制,这就是我尝试 Count 的原因,但即使有 NUM_ROWS 我也会很高兴。它显示错误:“ORA-00942:表或视图不存在 00942。00000 - “表或视图不存在”*原因:*操作:行错误:3 列:12”
  • 我稍微修改了我的要求。我只需要查看“user_tables”而不是“all_tables”。即使在那种情况下,仍然会出现错误:(
  • 使用可以访问DBA_TAB_MODIFICATIONS的登录名。
【解决方案3】:

我没有足够的代表发表评论但是 StevieG 的答案仍然返回错误的原因是因为您无权访问 dba_tab_modifications 视图,而是使用与您的权限一致的 user_ / all_ 等效项:

SELECT a.OWNER, a.TABLE_NAME, a.NUM_ROWS, b.TIMESTAMP
FROM ALL_TABLES a
INNER JOIN ALL_TAB_MODIFICATIONS b ON a.OWNER = b.TABLE_OWNER AND a.TABLE_NAME = b.TABLE_NAME

【讨论】:

    【解决方案4】:

    您的问题的解决方案很简单。 使用子查询分解。这肯定会对你有所帮助。

    在下面的链接中找到参考。

    http://oracle-base.com/articles/misc/with-clause.php

    【讨论】:

    • WITH 子句究竟将如何帮助解决这个问题?如果您尝试编写解决方案,您会发现它不会。
    • 你是对的,我没有尝试为这个确切的问题编写解决方案。问题是“在 Oracle Sql 中组合多个查询的结果”。答案很简单。
    • 你没有理解这个问题。 OP 希望使用 数据字典视图 的查询结果作为进一步查询的输入。 WITH 子句根本没有帮助。
    猜你喜欢
    • 2021-09-06
    • 2011-08-19
    • 2015-05-29
    • 2019-04-05
    • 2016-10-27
    • 1970-01-01
    • 1970-01-01
    • 2017-03-24
    • 2012-06-14
    相关资源
    最近更新 更多