Oracle过程显示表空间详细信息

时间:2019-01-29 14:17:41

标签: oracle plsql

运行此过程会出错。...尝试使用输入作为表名运行此过程并获取其空间使用情况统计信息...请帮助修复此问题

需要创建一个以表名作为输入并显示其空间详细信息(例如大小和行以及索引大小等)的过程

请帮助解决以下错误。

create or replace procedure sp_proc(input_owner IN VARCHAR2,input_table_name IN VARCHAR2)

as
  segment_size_blocks NUMBER;
  segment_size_bytes  NUMBER;
  used_blocks         NUMBER;
  used_bytes          NUMBER;
  expired_blocks      NUMBER;
  expired_bytes       NUMBER;
  unexpired_blocks    NUMBER;
  unexpired_bytes     NUMBER;
  total_blocks        NUMBER;
  total_bytes         NUMBER;
  unused_blocks       NUMBER;
  unused_bytes        NUMBER;
  last_ext_file_id    NUMBER;
  last_ext_blk_id     NUMBER;
  last_used_blk       NUMBER;
  result_table        NVARCHAR2(128);
  result_segment_type NVARCHAR2(128);
  result_used_kb      NUMBER;
  result_unused_kb    NUMBER;
  result_total_kb     NUMBER;
  CURSOR cur;
  begin
    SELECT
      s.segment_name   AS segment_name,
      s.owner          AS segment_owner,
      s.partition_name AS partition_name,
      s.segment_type   AS segment_type,
      CASE WHEN s.segment_type IN ('TABLE', 'TABLE PARTITION', 'TABLE SUBPARTITION')
        THEN s.segment_name
      WHEN s.segment_type IN ('INDEX', 'INDEX PARTITION', 'INDEX SUBPARTITION')
        THEN (SELECT i.table_name
              FROM dba_indexes i
              WHERE s.segment_name = i.index_name AND s.owner = i.owner)
      WHEN s.segment_type IN ('LOBSEGMENT', 'LOB PARTITION')
        THEN (SELECT l.table_name
              FROM dba_lobs l
              WHERE s.segment_name = l.segment_name AND s.owner = l.owner)
      WHEN s.segment_type IN ('LOBINDEX')
        THEN (SELECT l.table_name
              FROM dba_lobs l
              WHERE s.segment_name = l.index_name AND s.owner = l.owner)
      ELSE 'Unknown'
      END              AS table_name,
      s.bytes          AS segment_bytes
    FROM dba_segments s
    WHERE owner = input_owner
    and segment_name= input_table_name
    ORDER BY table_name, segment_type;

  dbms_output.put_line('name                                     data(KB)         unused(KB)');

  FOR ro IN cur
  LOOP

    result_table := ro.table_name;
    result_segment_type := ro.segment_type;

    IF ro.segment_type IN ('TABLE', 'INDEX')
    THEN
      dbms_space.unused_space(
          segment_owner             => ro.segment_owner,
          segment_name              => ro.segment_name,
          segment_type              => ro.segment_type,
          total_blocks              => total_blocks,
          total_bytes               => total_bytes,
          unused_blocks             => unused_blocks,
          unused_bytes              => unused_bytes,
          last_used_extent_file_id  => last_ext_file_id,
          last_used_extent_block_id => last_ext_blk_id,
          last_used_block           => last_used_blk);

      result_used_kb := (total_bytes - unused_bytes) / 1024;
      result_unused_kb := unused_bytes / 1024 ;
      result_total_kb := total_bytes / 1024 ;

    ELSIF ro.segment_type IN ('LOBSEGMENT')
    THEN
      dbms_space.space_usage(
          segment_owner           => ro.segment_owner,
          segment_name            => ro.segment_name,
          segment_type            => 'LOB',
          partition_name          => ro.partition_name,
          segment_size_blocks     => segment_size_blocks,
          segment_size_bytes      => segment_size_bytes,
          used_blocks             => used_blocks,
          used_bytes              => used_bytes,
          expired_blocks          => expired_blocks,
          expired_bytes           => expired_bytes,
          unexpired_blocks        => unexpired_blocks,
          unexpired_bytes         => unexpired_bytes
      );
      result_used_kb := used_bytes / 1024 ;
      result_unused_kb := (segment_size_bytes - used_bytes) / 1024 ;
      result_total_kb := segment_size_bytes / 1024;
    ELSE
      -- TODO ??
      result_used_kb := ro.segment_bytes / 1024 ;
      result_unused_kb := 0;
      result_total_kb := result_used_kb + result_unused_kb;
    END IF;

    dbms_output.put_line(
        RPAD(result_table, 30)  ||
        TO_CHAR(result_used_kb  / 1024 , '999999999990D00')||
        TO_CHAR(result_unused_kb  / 1024 , '999999999990D00'));

  END LOOP;
END;


LINE/COL ERROR
-------- -----------------------------------------------------------------
25/3     PL/SQL: Item ignored
25/3     PLS-00360: cursor declaration without body needs return type
27/5     PLS-00428: an INTO clause is expected in this SELECT statement
56/3     PL/SQL: Statement ignored
56/13    PLS-00320: the declaration of the type of this expression is
         incomplete or malformed

在上面运行此过程将上述错误作为警告...

1 个答案:

答案 0 :(得分:1)

您不能这样声明普通光标

  CURSOR cur; 

不指定查询或返回类型(通常为记录变量)

为使其简洁明了,请使用隐式游标循环。

CREATE OR REPLACE PROCEDURE sp_proc (
     input_owner        IN VARCHAR2,
     input_table_name   IN VARCHAR2
) AS
     segment_size_blocks   NUMBER;
     segment_size_bytes    NUMBER;
     used_blocks           NUMBER;
     used_bytes            NUMBER;
     expired_blocks        NUMBER;
     expired_bytes         NUMBER;
     unexpired_blocks      NUMBER;
     unexpired_bytes       NUMBER;
     total_blocks          NUMBER;
     total_bytes           NUMBER;
     unused_blocks         NUMBER;
     unused_bytes          NUMBER;
     last_ext_file_id      NUMBER;
     last_ext_blk_id       NUMBER;
     last_used_blk         NUMBER;
     result_table          NVARCHAR2(128);
     result_segment_type   NVARCHAR2(128);
     result_used_kb        NUMBER;
     result_unused_kb      NUMBER;
     result_total_kb       NUMBER;
BEGIN
     dbms_output.put_line('name                                     data(KB)         unused(KB)');
     FOR ro IN ( --implicit cursor loop
          SELECT s.segment_name AS segment_name,
                 s.owner AS segment_owner,
                 s.partition_name AS partition_name,
                 s.segment_type AS segment_type,
                 CASE
                      WHEN s.segment_type IN (
                           'TABLE',
                           'TABLE PARTITION',
                           'TABLE SUBPARTITION'
                      ) THEN s.segment_name
                      WHEN s.segment_type IN (
                           'INDEX',
                           'INDEX PARTITION',
                           'INDEX SUBPARTITION'
                      ) THEN (
                           SELECT i.table_name
                           FROM dba_indexes i
                           WHERE s.segment_name = i.index_name AND s.owner = i.owner
                      )
                      WHEN s.segment_type IN (
                           'LOBSEGMENT',
                           'LOB PARTITION'
                      ) THEN (
                           SELECT l.table_name
                           FROM dba_lobs l
                           WHERE s.segment_name = l.segment_name AND s.owner = l.owner
                      )
                      WHEN s.segment_type IN (
                           'LOBINDEX'
                      ) THEN (
                           SELECT l.table_name
                           FROM dba_lobs l
                           WHERE s.segment_name = l.index_name AND s.owner = l.owner
                      )
                      ELSE 'Unknown'
                 END
            AS table_name,
                 s.bytes AS segment_bytes
          FROM dba_segments s
          WHERE owner = input_owner AND segment_name = input_table_name
          ORDER BY table_name,
                   segment_type
     ) LOOP
          result_table := ro.table_name;
          result_segment_type := ro.segment_type;
          IF
               ro.segment_type IN (
                    'TABLE',
                    'INDEX'
               )
          THEN
               dbms_space.unused_space(segment_owner => ro.segment_owner,segment_name => ro.segment_name
              ,segment_type => ro.segment_type,total_blocks => total_blocks,total_bytes => total_bytes
              ,unused_blocks => unused_blocks,unused_bytes => unused_bytes,last_used_extent_file_id =>
                last_ext_file_id,last_used_extent_block_id => last_ext_blk_id,last_used_block => last_used_blk
               );
               result_used_kb := ( total_bytes - unused_bytes ) / 1024;
               result_unused_kb := unused_bytes / 1024;
               result_total_kb := total_bytes / 1024;
          ELSIF ro.segment_type IN (
               'LOBSEGMENT'
          ) THEN
               dbms_space.space_usage(segment_owner => ro.segment_owner,segment_name => ro.segment_name
              ,segment_type => 'LOB',partition_name => ro.partition_name,segment_size_blocks => segment_size_blocks
              ,segment_size_bytes => segment_size_bytes,used_blocks => used_blocks,used_bytes => used_bytes
              ,expired_blocks => expired_blocks,expired_bytes => expired_bytes,unexpired_blocks => unexpired_blocks
              ,unexpired_bytes => unexpired_bytes);
               result_used_kb := used_bytes / 1024;
               result_unused_kb := ( segment_size_bytes - used_bytes ) / 1024;
               result_total_kb := segment_size_bytes / 1024;
          ELSE
      -- TODO ??
               result_used_kb := ro.segment_bytes / 1024;
               result_unused_kb := 0;
               result_total_kb := result_used_kb + result_unused_kb;
          END IF;
          dbms_output.put_line(rpad(result_table,30) || TO_CHAR(result_used_kb / 1024,'999999999990D00'
          ) || TO_CHAR(result_unused_kb / 1024,'999999999990D00') );
     END LOOP;
END;
/

编译很好

Procedure SP_PROC compiled