CREATE OR REPLACE PROCEDURE SHOW_SPACE(P_SEGNAME IN VARCHAR2
,P_OWNER IN VARCHAR2 DEFAULT USER
,P_TYPE IN VARCHAR2 DEFAULT 'TABLE'
,P_PARTITION IN VARCHAR2 DEFAULT NULL)
-- this procedure uses authid current user so it can query DBA_*
-- views using privileges from a ROLE and so it can be installed
-- once per database, instead of once per user that wanted to use it
AUTHID CURRENT_USER AS
L_FREE_BLKS NUMBER;
L_TOTAL_BLOCKS NUMBER;
L_TOTAL_BYTES NUMBER;
L_UNUSED_BLOCKS NUMBER;
L_UNUSED_BYTES NUMBER;
L_LASTUSEDEXTFILEID NUMBER;
L_LASTUSEDEXTBLOCKID NUMBER;
L_LAST_USED_BLOCK NUMBER;
L_SEGMENT_SPACE_MGMT VARCHAR2(255);
L_UNFORMATTED_BLOCKS NUMBER;
L_UNFORMATTED_BYTES NUMBER;
L_FS1_BLOCKS NUMBER;
L_FS1_BYTES NUMBER;
L_FS2_BLOCKS NUMBER;
L_FS2_BYTES NUMBER;
L_FS3_BLOCKS NUMBER;
L_FS3_BYTES NUMBER;
L_FS4_BLOCKS NUMBER;
L_FS4_BYTES NUMBER;
L_FULL_BLOCKS NUMBER;
L_FULL_BYTES NUMBER;
-- inline procedure to print out numbers nicely formatted
-- with a simple label
PROCEDURE P(P_LABEL IN VARCHAR2, P_NUM IN NUMBER) IS
BEGIN
DBMS_OUTPUT.PUT_LINE(RPAD(P_LABEL, 40, '.') ||
TO_CHAR(P_NUM, '999,999,999,999'));
END;
BEGIN
-- this query is executed dynamically in order to allow this procedure
-- to be created by a user who has access to DBA_SEGMENTS/TABLESPACES
-- via a role as is customary.
-- NOTE: at runtime, the invoker MUST have access to these two
-- views!
-- this query determines if the object is a ASSM object or not
BEGIN
EXECUTE IMMEDIATE 'select ts.segment_space_management
from dba_segments seg, dba_tablespaces ts
where seg.segment_name = :p_segname
and (:p_partition is null or
seg.partition_name = :p_partition)
and seg.owner = :p_owner
and seg.tablespace_name = ts.tablespace_name'
INTO L_SEGMENT_SPACE_MGMT
USING P_SEGNAME, P_PARTITION, P_PARTITION, P_OWNER;
EXCEPTION
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('This must be a partitioned table, use p_partition => ');
RETURN;
END;
-- if the object is in an ASSM tablespace, we must use this API
-- call to get space information, else we use the FREE_BLOCKS
-- API for the user managed segments
IF L_SEGMENT_SPACE_MGMT = 'AUTO' THEN
DBMS_SPACE.SPACE_USAGE(P_OWNER
,P_SEGNAME
,P_TYPE
,L_UNFORMATTED_BLOCKS
,L_UNFORMATTED_BYTES
,L_FS1_BLOCKS
,L_FS1_BYTES
,L_FS2_BLOCKS
,L_FS2_BYTES
,L_FS3_BLOCKS
,L_FS3_BYTES
,L_FS4_BLOCKS
,L_FS4_BYTES
,L_FULL_BLOCKS
,L_FULL_BYTES
,P_PARTITION);
P('Unformatted Blocks ', L_UNFORMATTED_BLOCKS);
P('FS1 Blocks (0-25) ', L_FS1_BLOCKS);
P('FS2 Blocks (25-50) ', L_FS2_BLOCKS);
P('FS3 Blocks (50-75) ', L_FS3_BLOCKS);
P('FS4 Blocks (75-100)', L_FS4_BLOCKS);
P('Full Blocks ', L_FULL_BLOCKS);
ELSE
DBMS_SPACE.FREE_BLOCKS(SEGMENT_OWNER => P_OWNER
,SEGMENT_NAME => P_SEGNAME
,SEGMENT_TYPE => P_TYPE
,FREELIST_GROUP_ID => 0
,FREE_BLKS => L_FREE_BLKS);
P('Free Blocks', L_FREE_BLKS);
END IF;
-- and then the unused space API call to get the rest of the
-- information
DBMS_SPACE.UNUSED_SPACE(SEGMENT_OWNER => P_OWNER
,SEGMENT_NAME => P_SEGNAME
,SEGMENT_TYPE => P_TYPE
,PARTITION_NAME => P_PARTITION
,TOTAL_BLOCKS => L_TOTAL_BLOCKS
,TOTAL_BYTES => L_TOTAL_BYTES
,UNUSED_BLOCKS => L_UNUSED_BLOCKS
,UNUSED_BYTES => L_UNUSED_BYTES
,LAST_USED_EXTENT_FILE_ID => L_LASTUSEDEXTFILEID
,LAST_USED_EXTENT_BLOCK_ID => L_LASTUSEDEXTBLOCKID
,LAST_USED_BLOCK => L_LAST_USED_BLOCK);
P('Total Blocks', L_TOTAL_BLOCKS);
P('Total Bytes', L_TOTAL_BYTES);
P('Total MBytes', TRUNC(L_TOTAL_BYTES / 1024 / 1024));
P('Unused Blocks', L_UNUSED_BLOCKS);
P('Unused Bytes', L_UNUSED_BYTES);
P('Last Used Ext FileId', L_LASTUSEDEXTFILEID);
P('Last Used Ext BlockId', L_LASTUSEDEXTBLOCKID);
P('Last Used Block', L_LAST_USED_BLOCK);
END;
===============================================
分区表中的使用:
SQL> set serverout on
SQL> exec show_space('TABLE_NAME,'OWNER','TABLE PARTITION','PARTITION_NAME');