How to Compare Two Oracle 10g Schemas: A Practical Guide for Database Developers


2 views

When working with Oracle databases, developers often need to compare schemas to identify discrepancies. The standard approach using DBMS_METADATA.GET_DDL can produce output with too many trivial differences (like schema names) that obscure meaningful changes.

Here's a more effective method that filters out insignificant differences while preserving the structural information you actually care about:

-- For tables
SELECT 
    DBMS_METADATA.GET_DDL('TABLE', table_name) 
FROM 
    user_tables 
ORDER BY 
    table_name;

-- For indexes (with schema name removed)
SELECT 
    REGEXP_REPLACE(
        DBMS_METADATA.GET_DDL('INDEX', index_name),
        '".*?"\.', 
        ''
    ) 
FROM 
    user_indexes 
ORDER BY 
    index_name;

-- For triggers
SELECT 
    DBMS_METADATA.GET_DDL('TRIGGER', trigger_name) 
FROM 
    user_triggers 
ORDER BY 
    trigger_name;

For more precise comparisons, consider these additional strategies:

-- Compare table structures without storage parameters
SELECT 
    DBMS_METADATA.GET_DDL('TABLE', table_name, 'SCHEMA') 
FROM 
    user_tables 
WHERE 
    table_name NOT LIKE 'BIN$%'  -- exclude recyclebin objects
ORDER BY 
    table_name;

Create a script to generate comparable output from both schemas:

SET LONG 100000
SET LONGCHUNKSIZE 100000
SET LINESIZE 1000
SET PAGESIZE 0
SET TRIMSPOOL ON
SET ECHO OFF
SET FEEDBACK OFF

SPOOL schema_compare_&_schema_name..sql

-- Generate normalized DDL for all objects
BEGIN
    FOR t IN (SELECT table_name FROM user_tables ORDER BY table_name) LOOP
        DBMS_OUTPUT.PUT_LINE(
            REGEXP_REPLACE(
                DBMS_METADATA.GET_DDL('TABLE', t.table_name),
                '".*?"\.', 
                ''
            )
        );
    END LOOP;
    
    FOR i IN (SELECT index_name FROM user_indexes ORDER BY index_name) LOOP
        DBMS_OUTPUT.PUT_LINE(
            REGEXP_REPLACE(
                DBMS_METADATA.GET_DDL('INDEX', i.index_name),
                '".*?"\.', 
                ''
            )
        );
    END LOOP;
END;
/

SPOOL OFF

For complex schemas, consider specialized tools like:

  • Oracle SQL Developer's Database Diff feature
  • Redgate Schema Compare for Oracle
  • DBComparer

Remember to:

  1. Compare objects in a consistent order
  2. Normalize whitespace and formatting
  3. Exclude system-generated objects
  4. Consider using checksums for large objects

When working with complex Oracle databases, schema drift between environments is a common headache. The native approach using DBMS_METADATA often produces noisy diffs due to schema name inclusion and formatting variations. Here's how to get clean, comparable output.

The key is to transform the metadata into a standardized format. This Oracle PL/SQL block generates comparable DDL:


BEGIN
  -- Set transform parameters to exclude schema references
  DBMS_METADATA.SET_TRANSFORM_PARAM(
    DBMS_METADATA.SESSION_TRANSFORM,
    'SQLTERMINATOR', TRUE);
  DBMS_METADATA.SET_TRANSFORM_PARAM(
    DBMS_METADATA.SESSION_TRANSFORM,
    'REF_CONSTRAINTS', FALSE);
  DBMS_METADATA.SET_TRANSFORM_PARAM(
    DBMS_METADATA.SESSION_TRANSFORM,
    'OID', FALSE);
  DBMS_METADATA.SET_TRANSFORM_PARAM(
    DBMS_METADATA.SESSION_TRANSFORM,
    'SEGMENT_ATTRIBUTES', FALSE);
  DBMS_METADATA.SET_TRANSFORM_PARAM(
    DBMS_METADATA.SESSION_TRANSFORM,
    'TABLESPACE', FALSE);
END;

This comprehensive script generates diff-ready output for all critical schema objects:


-- Tables
SELECT 
  REPLACE(
    DBMS_METADATA.GET_DDL('TABLE', table_name),
    '"'||SYS_CONTEXT('USERENV','CURRENT_SCHEMA')||'".',
    '') 
FROM user_tables;

-- Indexes
SELECT 
  REPLACE(
    DBMS_METADATA.GET_DDL('INDEX', index_name),
    '"'||SYS_CONTEXT('USERENV','CURRENT_SCHEMA')||'".',
    '') 
FROM user_indexes;

-- Triggers
SELECT 
  REPLACE(
    DBMS_METADATA.GET_DDL('TRIGGER', trigger_name),
    '"'||SYS_CONTEXT('USERENV','CURRENT_SCHEMA')||'".',
    '') 
FROM user_triggers;

For large schemas, consider these approaches:

  1. Generate hash values for each object definition
  2. Compare only the hash values first to identify changed objects
  3. Use Oracle's Data Dictionary views for quick checks

For frequent comparisons, create a stored procedure that:


CREATE OR REPLACE PROCEDURE compare_schemas AS
  v_diff_count NUMBER := 0;
BEGIN
  -- Implementation would compare current schema with reference
  -- and report differences
  DBMS_OUTPUT.PUT_LINE('Schema comparison completed');
EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('Error: '||SQLERRM);
END;

While scripts work well, dedicated tools like:

  • Oracle SQL Developer's Database Diff
  • Redgate SQL Compare
  • DBComparer

offer more visual comparison features for complex schema differences.