www .Just SQL. com  

A Site by Peter Robson, for all those with an interest in Oracle's SQL*Plus....

Comparing 2 tables on their Primary Keys

Site Map

 set echo off
--
-- COMPARE_PK_FIELDS.SQL
--
-- Peter Robson
-- July 2003.
--
-- Script compares two tables on basis of their Primary Key.
-- Assumption - that both tables have identical PKs, in name and definition.
-- Other fields are not examined.
--
-- Output are the PKs of the rows unique to each table, presented in turn.
-- An intermediate table (xxx_compare_pk_keys) is built to hold column
-- constraint info, purely to avoid tedious joins across user_constraints
-- and  user_cons_columns (always a slow process) as PKs are constructed.
-- The PK-build script refers to this intermediate table only. This
-- temporary table is deleted once comparison is complete.
--
-- Structure is:
--
--   select pk1,pk2,pkn from MASTER       ... First comparison, Part 1
--   minus
--   select pk1,pk2,pkn from COPY;        ... First comparison, Part 2
--
--     repeat the above in reverse
--
--   select pk1,pk2,pkn from COPY         ... Second comparison, Part 1
--   minus
--   select pk1,pk2,pkn from MASTER;      ... Second comparison, Part 2
--
--  Note - there is a lot of repetition throughout this script, which might
--  be handled better by calling a series of sub-scripts as the same
--  repeated process is required. For reasons of clarity the entire script
--  is presented in full.
------------------------------
set pagesize 0
set linesize 2000
set trims on
set feedback off
set verify off
set scan on
--
-- device to ensure both spool files are empty
--
set sqlprompt "--"
spool a_master.sql
spool off
set sqlprompt ''
--
set sqlprompt "--"
spool a_copy.sql
spool off
set sqlprompt ''
--
-----------------------
--
-- insert a blank line before table prompts
--
select ' ' from dual;
--
-- Prompt for two tables to be compared:
--
prompt Enter name of tables to build comparison test against:
accept MASTER prompt ' Master Table: '
accept COPY   prompt '   Copy Table: '
accept DBLINK prompt ' Database Link (if used, and ONLY for Copy Table): '
--
set termout off
-----------------------
-- Build temp table xxx_compare_pk_keys to hold constraint info,
-- to save repeated table joins while constructing the PKs
--   This table dropped at end of script.
--
create table xxx_compare_pk_keys as
 select cc.owner,cc.constraint_name,cc.table_name,cc.column_name,position  from user_cons_columns cc,
 user_constraints uc
 where cc.owner = uc.owner
 and cc.constraint_name = uc.constraint_name
 and uc.constraint_type = 'P'
 and uc.table_name = upper('&MASTER');
------------------------
--
-- Build first half of process, testing MASTER uniqueness
--
spool a_master.sql
--
-- First comparison, Part 1.
--
-- 1st column where there is more than 1 column in the PK (1)
--
select
  'select '
from dual;
--
select
 '   '||column_name
from
 xxx_compare_pk_keys
where
 position =
 (select min(position)
  from xxx_compare_pk_keys
  )
and position <
 (select max(position)
  from xxx_compare_pk_keys
 )
;
--
--
-- building up the PK clause (2)
--
-- where 1st column is the only column
--
select
 '   '||column_name
from
 xxx_compare_pk_keys
where
 position =
 (select min(position)
  from xxx_compare_pk_keys
 )
and position =
 (select max(position)
  from xxx_compare_pk_keys
 )
;
--
--
-- building up the PK clause (3)
--
-- where these columns are neither the first nor the last columns
--
select
 ' , '||column_name
from
 xxx_compare_pk_keys
where
 position >
 (select min(position)
  from xxx_compare_pk_keys
 )
and position <
 (select max(position)
  from xxx_compare_pk_keys
 )
;
--
--
-- building up the PK clause (4)
--
-- where this column is the last, but not the first
--
select
 ' , '||column_name
from
 xxx_compare_pk_keys
where
 position >
 (select min(position)
  from xxx_compare_pk_keys
 )
and position =
 (select max(position)
  from xxx_compare_pk_keys
 )
;
--
-- build the phrase < from table_name >
--
select
   'from   &MASTER' from dual;
--
-- Now the binding component , 'minus'   ----------------- M I N U S
--
select 'minus ' from dual;
--
--
-- Repeat the previous construct for the second comparison table
--
-- First comparison, Part 2; Building up the second half of the comparison script
--
--
-- 1st column where there is more than 1 column in the PK
--
select
  'select '
from dual;
--
select
 '   '||column_name
from
 xxx_compare_pk_keys
where
 position =
 (select min(position)
  from xxx_compare_pk_keys
 )
and position <
 (select max(position)
  from xxx_compare_pk_keys
 )
;
--
--
-- building up the PK clause (2)
--
-- where 1st column is the only column
--
select
 '   '||column_name
from
 xxx_compare_pk_keys
where position =
 (select min(position)
  from xxx_compare_pk_keys
 )
and position =
 (select max(position)
  from xxx_compare_pk_keys
 )
;
--
--
-- building up the PK clause (3)
--
-- where these columns are neither the first nor the last columns
--
select
 ' , '||column_name
from
 xxx_compare_pk_keys
where
 position >
 (select min(position)
  from xxx_compare_pk_keys
 )
and position <
 (select max(position)
  from xxx_compare_pk_keys
 )
;
--
--
-- building up the PK clause (4)
--
-- where this column is the last, but not the first
--
select
 ' , '||column_name
from
 xxx_compare_pk_keys
where
 position >
 (select min(position)
  from xxx_compare_pk_keys
 )
and position =
 (select max(position)
  from xxx_compare_pk_keys
 )
;
--
-- build the phrase < from table_name >
--
select 'from '||'&COPY'||'&DBLINK ;' from dual;
--
--
spool off
--
--------------- end of First comparison  -----------------------------
--
-- Build second half of process, testing MASTER uniqueness
--
spool a_copy.sql
--
-- Second comparison, Part 1.
--
-- 1st column where there is more than 1 column in the PK (1)
--
select
  'select '
from dual;
--
select
 '   '||column_name
from
 xxx_compare_pk_keys
where
 position =
 (select min(position)
  from xxx_compare_pk_keys
 )
and position <
 (select max(position)
  from xxx_compare_pk_keys
 )
;
--
--
-- building up the PK clause (2)
--
-- where 1st column is the only column
--
select
 '   '||column_name
from
 xxx_compare_pk_keys
where
 position =
 (select min(position)
  from xxx_compare_pk_keys
 )
and position =
 (select max(position)
  from xxx_compare_pk_keys
 )
;
--
--
-- building up the PK clause (3)
--
-- where these columns are neither the first nor the last columns
--
select
 ' , '||column_name
from
 xxx_compare_pk_keys
where
 position >
 (select min(position)
  from xxx_compare_pk_keys
 )
and position <
 (select max(position)
  from xxx_compare_pk_keys
 )
;
--
--
-- building up the PK clause (4)
--
-- where this column is the last, but not the first
--
select
 ' , '||column_name
from
 xxx_compare_pk_keys
where
 position >
 (select min(position)
  from xxx_compare_pk_keys
 )
and position =
 (select max(position)
  from xxx_compare_pk_keys
 )
;
--
-- build the phrase < from table_name >
--
select
   'from   &COPY'||'&DBLINK' from dual;
--
-- Now the binding component , 'minus'   ----------------- M I N U S
--
select 'minus ' from dual;
--
--
-- Repeat the previous construct for the second comparison table
--
-- Second comparison, Part 2; Building up the second half of the comparison script
--
--
-- 1st column where there is more than 1 column in the PK
--
select
  'select '
from dual;
--
select
 '   '||column_name
from
 xxx_compare_pk_keys
where
 position =
 (select min(position)
  from xxx_compare_pk_keys
 )
and position <
 (select max(position)
  from xxx_compare_pk_keys
 )
;
--
--
-- building up the PK clause (2)
--
-- where 1st column is the only column
--
select
 '   '||column_name
from
 xxx_compare_pk_keys
where
 position =
 (select min(position)
  from xxx_compare_pk_keys
 )
and position =
 (select max(position)
  from xxx_compare_pk_keys
 )
;
--
--
-- building up the PK clause (3)
--
-- where these columns are neither the first nor the last columns
--
select
 ' , '||column_name
from
 xxx_compare_pk_keys
where
 position >
 (select min(position)
  from xxx_compare_pk_keys
 )
and position <
 (select max(position)
  from xxx_compare_pk_keys
 )
;
--
--
-- building up the PK clause (4)
--
-- where this column is the last, but not the first
--
select
 ' , '||column_name
from
 xxx_compare_pk_keys
where
 position >
 (select min(position)
  from xxx_compare_pk_keys
 )
and position =
 (select max(position)
  from xxx_compare_pk_keys
 )
;
--
-- build the phrase < from table_name >
--
select 'from '||'&MASTER'||' ;' from dual;
--
--
spool off
--
--
--------------- end of Second comparison.
set termout off
--
--
spool spooler.txt
select
 'spool &MASTER'||'_COPY.txt' from dual;
spool off
@spooler.txt
--
------------------ Complete scripts written; drop intermediat
--                 table 'xxx_compare_pk_keys' and run the scripts.
--
drop table xxx_compare_pk_keys;
--
set termout on
--
select ' ' from dual;
select
'Rows in '||upper('&MASTER')||' defined by PK that are absent from '||upper('&COPY')||' :'
from dual;
--
set sqlprompt "SQL>"
set feedback 6
set pagesize 999
set trims on
--
@a_master.sql
--
set pagesize 0
--
select
'Rows in '||upper('&COPY')||' defined by PK that are absent from '||upper('&MASTER')||' :'
from dual;
--
set pagesize 999
--
@a_copy.sql
--
set heading on
set trims off
set scan on
set feedback on
set verify on
set pagesize 999
set sqlprompt 'SQL>'
set echo on
 

 

e-Mail Contact