Процедура Oracle для отображения информации о табличном пространстве - PullRequest
0 голосов
/ 29 января 2019

Ошибка запуска этой процедуры .... попытка запустить это с вводом в качестве имени таблицы и получить статистику использования пространства ... пожалуйста, помогите исправить это

Необходимо создать процедуру, принимающую имя таблицы в качестве вводаи отображение его пробелов, таких как размер, строки и размер индекса и т. д.

Пожалуйста, помогите исправить ошибки ниже.

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 голосов
/ 29 января 2019

Вы не можете объявить простой курсор как этот

  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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...