如何列出其中包含数据的所有表?

How to list all tables that have data in it?

我有大约 2000 个表,其中大部分未使用并且其中没有任何数据。 我知道如何列出所有表格如下

SELECT owner, table_name FROM ALL_TABLES

但我不知道如何列出其中至少有一行数据的列表。 有办法吗?

有几种方法可以做到这一点:

  • Brute-force 并计算每个 table
  • 中的行数
  • 查看 table 统计数据
  • 检查是否有分配的存储空间

暴力破解

循环遍历 table 行,计算行数,并吐出空行:

declare
  c integer;
begin
  for t in (
    select table_name from user_tables
    where  external = 'NO'
    and    temporary = 'N'
  ) loop
    execute immediate 
      'select count(*) from ' || t.table_name
    into c;
    if c = 0 then
      dbms_output.put_line ( t.table_name );
    end if;
  end loop;
end;
/

这是确保 table 现在 中没有行的唯一方法。这样做的主要缺点是,如果您有许多 table 具有数百万行以上,则可能需要很长时间。

我排除了:

  • 临时 table秒。您只能看到插入到会话中的数据。如果它们正在另一个会话中使用,您将看不到这个
  • 外部 tables。这些指向数据库服务器文件系统上的文件。这些文件可能是临时 missing/blank/etc.

可能还有其他 table 类型存在此类问题 - 请务必仔细检查任何报告为空的类型。

查看统计数据

如果所有 table 统计数据都是 up-to-date,您可以查看 num_rows:

select table_name
from   user_tables ut
where  external = 'NO'
and    temporary = 'N'
and    num_rows = 0;

需要注意的是这个数字可能是 out-of-date。您现在可以通过 运行ning:

强制重新收集
exec dbms_stats.gather_schema_stats ( user );

尽管这可能需要一段时间,而且 - 如果收集已经 disabled/deferred - 可能会导致计划发生不必要的更改。避免在您的生产数据库上执行此操作!

检查存储分配

您可以查找 table 没有分配的段:

select table_name 
from   user_tables ut
where  external = 'NO'
and    temporary = 'N'
and    segment_created = 'NO';

因为没有 space 分配给这些,所以肯定没有行!但是 table 可以分配 space 但其中没有行。因此它可能会省略一些空的 tables - 对于过去确实有行但现在为空的 tables 特别有可能。

最后的想法

值得记住的是 table 没有行 现在 仍然可以使用。用于 daily/weekly/monthly 加载的分段 table 可能会在过程结束时被清除;删除这些仍然会破坏您的应用程序!

也可能有引用空 table 的代码可以工作 as-is,但如果删除 table.

就会出错

更好的方法是启用审计,然后 运行 这“一段时间”。在该时间段内任何 table 都不会被审核访问 可能 可以安全删除。