You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle中遍历TB_前缀表并获取表大小的PL/SQL问题排查

解决Oracle PL/SQL查询TB_开头表大小的报错问题

错误原因及修正点

  • 类型不匹配错误(PLS-00382):
    游标循环变量my_table_name是游标返回的记录类型,而非单纯的字符串。直接用WHERE segment_name=my_table_name会把记录类型和字符串类型做比较,导致类型错误。正确写法是引用记录中的table_name字段:WHERE segment_name = my_table_name.table_name。

  • 查询范围不匹配:
    all_tables会返回所有用户下符合条件的表,但user_segments仅包含当前登录用户的段信息。如果TB_开头的表属于其他用户,用user_segments查不到数据。建议改用dba_segments(需对应权限),同时在游标中获取表的所属用户(owner),过滤时加上owner条件,避免不同用户下同名表的混淆。

  • NULL值处理:
    当表未分配段(比如新建的空表),SUM(bytes)会返回NULL,输出时可以用NVL函数将NULL转为0,避免输出混乱。

  • 语法细节:
    PL/SQL块结尾需要加;,DBMS_OUTPUT.put_line语句结尾也需要加;。


修正后的完整代码(支持跨用户查询)

DECLARE
  CURSOR my_cursor IS
    SELECT owner, table_name
    FROM all_tables
    WHERE table_name LIKE 'TB_%'
    ORDER BY owner, table_name ASC;
  my_size NUMBER;
BEGIN
  FOR rec IN my_cursor LOOP
    SELECT NVL(SUM(bytes)/1024/1024, 0) INTO my_size
    FROM dba_segments
    WHERE segment_name = rec.table_name
      AND owner = rec.owner
      AND segment_type = 'TABLE'; -- 仅查询表段,排除索引等其他段
    
    DBMS_OUTPUT.put_line(rec.owner || '.' || rec.table_name || ' : ' || my_size || ' MB');
  END LOOP;
END;
/

无DBA权限时的替代方案(仅查当前用户表)

DECLARE
  CURSOR my_cursor IS
    SELECT table_name
    FROM user_tables -- 仅查询当前用户的表
    WHERE table_name LIKE 'TB_%'
    ORDER BY table_name ASC;
  my_size NUMBER;
BEGIN
  FOR rec IN my_cursor LOOP
    SELECT NVL(SUM(bytes)/1024/1024, 0) INTO my_size
    FROM user_segments
    WHERE segment_name = rec.table_name
      AND segment_type = 'TABLE';
    
    DBMS_OUTPUT.put_line(rec.table_name || ' : ' || my_size || ' MB');
  END LOOP;
END;
/

内容的提问来源于stack exchange,提问作者david

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 02:20:20