我在 Oracle 中有一组表,我想确定包含最大行数的表。
因此,如果 A 有 200 行,B 有 345 行,C 有 120 行,我希望能够识别表 B。
我可以运行一个简单的查询来实现这一点吗?
编辑:有 100 多个表,所以我正在寻找通用的东西。
鉴于您说您使用的是 Oracle,我只会查询元数据。
select table_name, max(num_rows) from all_tables where table_name in ('A', 'B', 'C');
刚看到你的编辑。只需在没有 where 子句的情况下运行上面的代码,它将返回数据库中最大的表。唯一的问题可能是您可能会得到一个 SYS$ 表或其他东西。或者,如果您只是为了自己的知识而这样做
select table_name, num_rows from all_tables order by num_rows;
你会看到最大的是什么。
架构中具有最大行数的表:
with data as
(
select table_name,
to_number(extractvalue(xmltype(
dbms_xmlgen.getxml (
' select count(*) c from ' || table_name)),
'/ROWSET/ROW/C')) countrows
from user_tables
)
select table_name, countrows
from data
where countrows = (select max(countrows)
from data);
dbms_xmlgen.getxml(' select .... ') 非常灵活。
这是另一种方法,可能比简单地获取 ALL_TABLES.NUM_ROWS 慢得多,但它不依赖于已收集的统计数据并给出准确的当前值 - 尽管当前值取决于运行所需的时间!
-- For running in SQLPlus you need this to see the output.
-- If running in Toad or similar tool, output is enabled by default
SET SERVEROUTPUT ON SIZE 100000
DECLARE
l_rows INTEGER;
l_max_rows INTEGER := 0;
l_table_name all_tables.table_name%TYPE := NULL;
BEGIN
FOR table_record IN (SELECT table_name FROM all_tables) LOOP
EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM '||table_record.table_name
INTO l_rows;
IF l_rows > l_max_rows THEN
l_max_rows := l_rows;
l_table_name := table_record.table_name;
END IF;
END LOOP;
IF l_table_name IS NULL THEN
dbms_output.put_line( 'All tables are empty' );
ELSE
dbms_output.put_line( 'Table ' || table_record.table_name ||
' has ' || TO_CHAR(l_max_rows) || ' rows'
);
END IF;
END;
/
select max(select count(*) from A union select count(*) from B...)
应该管用。
编辑:如果你想要一些动态的东西,你可以在 PL/SQL 中使用每个“count(*)”子查询构建一个字符串(例如,列出来自 USER_TABLES 的表名),然后使用以下命令执行主查询:
execute immediate 'select max('||subquery||')'
您可以使用这样的数据拖网获得相同的结果:
SELECT DISTINCT
FIRST_VALUE ( t.owner )
OVER ( ORDER BY t.num_rows DESC NULLS LAST )
owner,
FIRST_VALUE ( t.table_name )
OVER ( ORDER BY t.num_rows DESC NULLS LAST )
table_name,
FIRST_VALUE ( t.num_rows )
OVER ( ORDER BY t.num_rows DESC NULLS LAST )
num_rows
FROM all_tables t
David Aldridge 正确地指出,查询 all_tables 可能会由于缺少或陈旧的表统计信息而给出不正确的结果。但是使用user_segments也有问题;高水位线以下的已删除块仍将计入表的大小。
例子:
SQL>create table t as select * from all_objects
Table created.
SQL>select blocks, bytes from user_segments where segment_name = 'T';
BLOCKS BYTES
---------- ----------
768 6291456
SQL>delete from t
52676 rows deleted.
SQL>commit;
Commit complete.
SQL>select count(*) from t;
COUNT(*)
----------
0
SQL>select blocks, bytes from user_segments where segment_name = 'T';
BLOCKS BYTES
---------- ----------
768 6291456
SQL>truncate table t;
Table truncated.
SQL>select blocks, bytes from user_segments where segment_name = 'T';
BLOCKS BYTES
---------- ----------
8 65536
这是一个查询,用于获取数据库表中的最大行数。
select table_name, num_rows from USER_TABLES
where num_rows = (select max(num_rows) from
(select table_name, num_rows from USER_TABLES));