需要编写一个 sql 脚本来查找 oracle 中任何数据库的元数据详细信息

Posted

技术标签:

【中文标题】需要编写一个 sql 脚本来查找 oracle 中任何数据库的元数据详细信息【英文标题】:Need to write one sql script to find the metadata details of any database in oracle 【发布时间】:2013-02-13 17:21:51 【问题描述】:

我的目标是使用 PL/SQL 在 Oracle 中编写一个脚本,以从以下格式的数据库表中获取数据。

table_name|table_size|avg_row_length

我需要数据库中所有可用的表。以下是尝试编写以获取特定架构的上述详细信息的脚本。但是我得到以下错误

PLS-00103:在预期以下情况之一时遇到符号“AVG_ROW_SIZE”: := ;不为空默认字符

SET serveroutput on;
clear screen;

set lin 20000;
set trimspool on;
set feed off;
set verify off;
set head off;

spool &&1..metadata_report.out

DECLARE
    v_tbl_name   VARCHAR2(1500);
    v_row_num    NUMBER(20);
    table_size   NUMBER(20);
    avg_row_size NUMBER(30);
    CURSOR c1 IS
      SELECT DISTINCT table_name
      FROM   all_tables
      WHERE  owner = Upper('&&1')
      ORDER  BY table_name ASC;
    c1_rec       c1%ROWTYPE;
BEGIN
    OPEN c1;

    LOOP
        FETCH c1 INTO c1_rec;

        exit WHEN c1%NOTFOUND;

        EXECUTE IMMEDIATE
'select sum((bytes/1024)) from user_extents where segment_name = "'||c1_rec.table_name||'"' INTO
table_size;

EXECUTE IMMEDIATE
'select decode(count(*),NULL,0, count(*)) FROM &&1.."'||c1_rec.table_name||'"'
    INTO v_row_num;

IF( v_row_num = 0 ) THEN
  avg_row_size := 0;
ELSE
  EXECUTE IMMEDIATE 'SELECT table_size/v_row_num FROM DUAL' INTO avg_row_size;
END IF;

dbms_output.Put_line(c1_rec.table_name
                     ||'|'
                     ||table_size
                     ||'|'
                     ||avg_row_size);
END LOOP;

CLOSE c1;
END; 

/

【问题讨论】:

粘贴脚本应该不是问题 - 使用 ctrl+K 将代码添加到您的帖子中。至少你可以命名你正在查询的表。 不知何故我添加了脚本..现在请帮助我.. 您有什么要求?您正在查询all_tables,然后点击user_extents。您是否假设此脚本将以拥有表的用户身份运行?或者您想为可能不是当前用户模式的特定模式中的所有表运行它?定义表的大小?我们应该排除与表关联的LOB 段吗?物联网的溢出区域?定义行的平均大小。您是否只想将其定义为表段的大小除以表中的行数? 是的...我也可以使用 all_extents..我想将所有者作为文件的输入...我给了 &&1。我们可以排除吊球............不需要......是的 【参考方案1】:

鉴于错误,并且没有看到您的脚本,我猜测您正试图从DBA_TABLES 获取此信息,并且您想使用AVG_ROW_LEN 列但输入的名称错误为AVG_ROW_SIZE。我的猜测是您正在尝试编写查询

SELECT table_name, num_rows * avg_row_len, avg_row_len
  FROM dba_tables

但请注意,DBA_TABLES 中的数据可能不正确。充其量,它是上次在表上收集统计信息时表状态的近似值。但完全有可能从未在表格上收集过统计数据。或者当表的数据量非常少时收集统计信息,现在它有数十亿行。但是,在许多情况下,可以合理地假设统计数据相当准确,并且这些近似值足够接近。当然,您确实希望将OWNER 列添加到查询中,因为单个数据库中可能有许多同名的不同表。

您也可能会被定义绊倒。一张桌子的“平均行长”或“一张桌子的大小”对不同的人来说可能意味着非常不同的东西。例如,如果您的表包含一个外行的LOB,会发生什么情况?由于LOB 未存储在表的段中,您在计算表的大小时是否计算了LOB 的大小?如果向表中添加一百万个空块,平均行长度会改变吗?如果您想将其定义为表的大小除以行数,则可以。如果您想将其定义为从表中获取一行数据时将返回的平均数据量,则不会。

如果您想要更准确,可以使用DBA_SEGMENTS 表来获取磁盘上各个段的大小。但是,根据您的定义,您可能需要使用其他数据字典表(如 DBA_LOBS)来确定哪些 LOB 段与特定表相关,以便将它们包含在表大小的计算中。您可以使用DBMS_SPACE 包来获取有关表中空白空间量的信息,如果您想取消它的话。如果您想准确计算表中的行数,则需要执行SELECT COUNT(*) FROM table_name,这可能会非常昂贵。

【讨论】:

可以将正在编写的脚本通过电子邮件发送给您。这可以给你更多的理解。你能告诉我你的电子邮件地址吗? bcz 对我来说格式更重要,我想将输出写入测试文件。我知道 dba_tables 中的值不准确,所以我需要好的值..bcz 将获取生产数据并将其用作我的其他脚本之一的输入...如果可能,请帮助我。 . @SrikanthGoudLingaala - 随意编辑您的帖子以包含您的脚本。这样其他人,不仅仅是我,也可以看到它。如果您想要更准确的结果,您还需要编辑您的问题以包含您想要使用的“表格大小”和“平均行长度”的精确定义。 现在添加了脚本..请纠正我或让我知道我是否可以写得更好..上面的脚本给出错误...我需要一些该格式的脚本..我想你得到了我的要求。 @Srikanth Goud Lingaala - 你从贾斯汀那里得到答案了吗?为什么您的代码中需要所有这些动态 SQL?为什么在 PL/SQL 中使用“&&1”?这是错误的,只能在 SQL 中使用的替换参数... 我仍然没有得到任何答案...如果我的脚本是错误的..你能帮我写正确的 1 吗?我想你得到了我的要求.....n 使用 th &&1 作为模式名称提供输入【参考方案2】:

这是 calc avg row len 的示例:http://www.dba-oracle.com/t_average_row_length.htm 您可以添加其余的...不需要 PL/SQL。

【讨论】:

【参考方案3】:

关于 table_size,您应该总结所有分配的块,而不是乘以计算的平均行长度和基于创建的统计信息的行数。只需考虑具有大量删除(除其他外)的未重用块或表。 This and other database related information needed for optimisation is available in QueryAdvisor.

【讨论】:

以上是关于需要编写一个 sql 脚本来查找 oracle 中任何数据库的元数据详细信息的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Oracle SQL 中查找最具体的匹配行

如何批量执行sql查找替换?

在 Oracle SQL Developer 中识别非空表

什么时候需要在 Oracle SQL 中使用分号和斜杠?

用于从其他表中查找数据的 SQL / Oracle SQL 代码

是否可以在 Oracle SQL*plus 脚本中以编程方式构造替换变量的名称?