Comments on: Compare tables with the minus operator, even if they contain clobs and/or blobs. https://technology.amis.nl/2012/07/04/compare-tables-with-the-minus-operator-even-if-they-contain-clobs-andor-blobs/ Friends of Oracle and Java Fri, 27 Feb 2015 08:30:27 +0000 hourly 1 http://wordpress.org/?v=4.1.1 By: Harry Dragstra https://technology.amis.nl/2012/07/04/compare-tables-with-the-minus-operator-even-if-they-contain-clobs-andor-blobs/#comment-7236 Fri, 06 Jul 2012 09:26:16 +0000 http://technology.amis.nl/?p=18454#comment-7236 Well, you better forget about my last comment… the ORA_HASH function, used in the way I do, isn’t consistent in the result value.
And if result values differ in time for identical input, comparing two tables that use this function will (almost ) always result in 1 ( tables differ ).
See for more info about the ORA_HASH function:
http://jonathanlewis.wordpress.com/2009/11/21/ora_hash-function/

]]>
By: Harry Dragstra https://technology.amis.nl/2012/07/04/compare-tables-with-the-minus-operator-even-if-they-contain-clobs-andor-blobs/#comment-7234 Fri, 06 Jul 2012 07:49:47 +0000 http://technology.amis.nl/?p=18454#comment-7234 I discovered that there is an easy ( without using dbms_lob.compare ) full proof solution, by applying
the ORA_HASH function ( available as of 10g Release 1 ).

The docs – http://docs.oracle.com/cd/B13789_01/server.101/b10759/functions097.htm – mention explicitly that there is “no restrictions on the type or length of data”, so I tested it on LONG’s too.
And indeed… no problem at all.

Here is the the changed code, using the ORA_HASH function now:

SQL> set linesize 300 pagesize 0 heading off
SQL> select text from user_source where type=’FUNCTION’ and name =’DIFF_TABLES’ order by line;
FUNCTION Diff_Tables
( P_name_tab1 VARCHAR2
, P_name_tab2 VARCHAR2
, P_owner_tab1 VARCHAR2 := USER
, P_owner_tab2 VARCHAR2 := USER )
RETURN PLS_INTEGER
IS

v_tab1 VARCHAR2(100) := UPPER(TRIM(P_owner_tab1||’.’||P_name_tab1));
v_tab2 VARCHAR2(100) := UPPER(TRIM(P_owner_tab2||’.’||P_name_tab2));
v_clist VARCHAR2(4000) := NULL;
v_col VARCHAR2(100);
cntr PLS_INTEGER := 0;
cnt1 NUMBER := 0;
cnt2 NUMBER := 0;
v_ret PLS_INTEGER := 0;

BEGIN

— setup the column list
for x in ( select column_name
, data_type
from dba_tab_columns
where owner||’.’||table_name = v_tab1
order by column_id )
loop
cntr := cntr + 1;
if x.data_type in (‘CLOB’,’BLOB’,’LONG’) then
v_col := ‘ORA_HASH(‘||x.column_name||’)';
— v_col := ‘DBMS_LOB.SUBSTR(‘||x.column_name||’,2000), DBMS_LOB.GETLENGTH(‘||x.column_name||’)';
else
v_col := x.column_name;
end if;
if cntr != 1 then
v_col := ‘,’||v_col;
end if;
v_clist := v_clist||v_col;
end loop;

— compare
EXECUTE IMMEDIATE ‘select count(*) from ( select ‘||v_clist||’ from ‘||v_tab1||’ minus select ‘||v_clist||’ from ‘||v_tab2||’ )’ INTO cnt1;
EXECUTE IMMEDIATE ‘select count(*) from ( select ‘||v_clist||’ from ‘||v_tab2||’ minus select ‘||v_clist||’ from ‘||v_tab1||’ )’ INTO cnt2;

— return 0 if tables match, and 1 if tables differ.
if (cnt1+cnt2) > 0 then
v_ret := 1;
end if;

return v_ret;

END Diff_Tables;

50 rows selected.

SQL>

]]>