-- ====================================================================================

-- Script Name : unused_objects_report.sql

-- Purpose     : Identify unused or stale objects based on user-defined inactivity days

-- Author      : ChatGPT for Raunak

-- ====================================================================================


SET ECHO OFF

SET LINESIZE 200

SET PAGESIZE 100

SET FEEDBACK OFF

SET VERIFY OFF

SET TRIMSPOOL ON


-- === Accept user input for age threshold ===

ACCEPT v_days NUMBER PROMPT 'Enter number of days to consider an object as UNUSED (e.g., 90): '


-- === Generate timestamped spool file ===

COLUMN spool_file_name NEW_VALUE spool_file

SELECT 'unused_objects_' || TO_CHAR(SYSDATE, 'YYYYMMDD_HH24MISS') || '.lst' AS spool_file_name FROM dual;

SPOOL &spool_file


PROMPT ============================================================================

PROMPT Report: Objects Unused for at least &v_days days

PROMPT ============================================================================


COLUMN OWNER           FORMAT A20

COLUMN OBJECT_NAME     FORMAT A30

COLUMN OBJECT_TYPE     FORMAT A20

COLUMN STATUS          FORMAT A10

COLUMN CREATED         FORMAT A20

COLUMN LAST_DDL_TIME   FORMAT A20

COLUMN SEGMENT_SIZE_MB FORMAT 999,999.99

COLUMN LAST_ANALYZED   FORMAT A20


SELECT

    o.owner,

    o.object_name,

    o.object_type,

    o.status,

    o.created,

    o.last_ddl_time,

    ROUND(NVL(s.bytes, 0)/1024/1024, 2) AS segment_size_mb,

    CASE 

        WHEN o.object_type = 'TABLE' THEN t.last_analyzed 

        ELSE NULL 

    END AS last_analyzed

FROM 

    dba_objects o

LEFT JOIN 

    dba_segments s 

    ON o.owner = s.owner 

    AND o.object_name = s.segment_name 

    AND s.segment_type = o.object_type

LEFT JOIN 

    dba_tab_statistics t 

    ON o.owner = t.owner 

    AND o.object_name = t.table_name 

    AND o.object_type = 'TABLE'

WHERE 

    o.owner NOT IN ('SYS', 'SYSTEM', 'SYSMAN', 'DBSNMP')

    AND o.object_type IN ('TABLE', 'INDEX', 'VIEW', 'MATERIALIZED VIEW')

    AND (

        o.last_ddl_time < SYSDATE - &v_days

        OR (o.object_type = 'TABLE' AND (t.last_analyzed IS NULL OR t.last_analyzed < SYSDATE - &v_days))

    )

    AND (s.bytes IS NULL OR s.bytes = 0 OR s.bytes < 1024*1024) -- < 1 MB

ORDER BY 

    o.owner, o.object_type, o.object_name;


PROMPT ============================================================================

PROMPT Done. Report saved to &spool_file

PROMPT ============================================================================

SPOOL OFF


Popular posts from this blog