<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Compare tables with the minus operator, even if they contain clobs and/or blobs.</title>
	<atom:link href="http://technology.amis.nl/2012/07/04/compare-tables-with-the-minus-operator-even-if-they-contain-clobs-andor-blobs/feed/" rel="self" type="application/rss+xml" />
	<link>http://technology.amis.nl/2012/07/04/compare-tables-with-the-minus-operator-even-if-they-contain-clobs-andor-blobs/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=compare-tables-with-the-minus-operator-even-if-they-contain-clobs-andor-blobs</link>
	<description></description>
	<lastBuildDate>Tue, 11 Jun 2013 22:09:58 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
	<item>
		<title>By: Harry Dragstra</title>
		<link>http://technology.amis.nl/2012/07/04/compare-tables-with-the-minus-operator-even-if-they-contain-clobs-andor-blobs/#comment-7236</link>
		<dc:creator>Harry Dragstra</dc:creator>
		<pubDate>Fri, 06 Jul 2012 09:26:16 +0000</pubDate>
		<guid isPermaLink="false">http://technology.amis.nl/?p=18454#comment-7236</guid>
		<description><![CDATA[Well, you better forget about my last comment... the ORA_HASH function, used in the way I do, isn&#039;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/]]></description>
		<content:encoded><![CDATA[<p>Well, you better forget about my last comment&#8230; the ORA_HASH function, used in the way I do, isn&#8217;t consistent in the result value.<br />
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 ).<br />
See for more info about the ORA_HASH function:<br />
<a href="http://jonathanlewis.wordpress.com/2009/11/21/ora_hash-function/" rel="nofollow">http://jonathanlewis.wordpress.com/2009/11/21/ora_hash-function/</a></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Harry Dragstra</title>
		<link>http://technology.amis.nl/2012/07/04/compare-tables-with-the-minus-operator-even-if-they-contain-clobs-andor-blobs/#comment-7234</link>
		<dc:creator>Harry Dragstra</dc:creator>
		<pubDate>Fri, 06 Jul 2012 07:49:47 +0000</pubDate>
		<guid isPermaLink="false">http://technology.amis.nl/?p=18454#comment-7234</guid>
		<description><![CDATA[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 - mentione explicitly 
that there is &quot;no restrictions on the type or length of data&quot;, so I tested it on LONG&#039;s too.
And indeed... no problem at all.

Here is the the changed code, using the ORA_HASH function now: 

&lt;code&gt;
SQL&gt; set linesize 300 pagesize 0 heading off    
SQL&gt; select text from user_source where type=&#039;FUNCTION&#039; and name =&#039;DIFF_TABLES&#039; 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&#124;&#124;&#039;.&#039;&#124;&#124;P_name_tab1));
  v_tab2   VARCHAR2(100)  := UPPER(TRIM(P_owner_tab2&#124;&#124;&#039;.&#039;&#124;&#124;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&#124;&#124;&#039;.&#039;&#124;&#124;table_name = v_tab1
             order by column_id )
  loop
    cntr := cntr + 1;
    if x.data_type in (&#039;CLOB&#039;,&#039;BLOB&#039;,&#039;LONG&#039;) then
      v_col := &#039;ORA_HASH(&#039;&#124;&#124;x.column_name&#124;&#124;&#039;)&#039;;
--      v_col := &#039;DBMS_LOB.SUBSTR(&#039;&#124;&#124;x.column_name&#124;&#124;&#039;,2000), DBMS_LOB.GETLENGTH(&#039;&#124;&#124;x.column_name&#124;&#124;&#039;)&#039;;
    else
      v_col := x.column_name;
    end if;
    if cntr != 1 then
      v_col := &#039;,&#039;&#124;&#124;v_col;
    end if;
    v_clist := v_clist&#124;&#124;v_col;
  end loop;

-- compare
  EXECUTE IMMEDIATE &#039;select count(*) from ( select &#039;&#124;&#124;v_clist&#124;&#124;&#039; from &#039;&#124;&#124;v_tab1&#124;&#124;&#039; minus select &#039;&#124;&#124;v_clist&#124;&#124;&#039; from &#039;&#124;&#124;v_tab2&#124;&#124;&#039; )&#039; INTO cnt1;
  EXECUTE IMMEDIATE &#039;select count(*) from ( select &#039;&#124;&#124;v_clist&#124;&#124;&#039; from &#039;&#124;&#124;v_tab2&#124;&#124;&#039; minus select &#039;&#124;&#124;v_clist&#124;&#124;&#039; from &#039;&#124;&#124;v_tab1&#124;&#124;&#039; )&#039; INTO cnt2;

-- return 0 if tables match, and 1 if tables differ.
  if (cnt1+cnt2) &gt; 0 then
    v_ret := 1;
  end if;

  return v_ret;

END Diff_Tables;

50 rows selected.

SQL&gt;
&lt;/code&gt;]]></description>
		<content:encoded><![CDATA[<p>I discovered that there is an easy ( without using dbms_lob.compare ) full proof solution, by applying<br />
the ORA_HASH function ( available as of 10g Release 1 ). </p>
<p>The docs &#8211; <a href="http://docs.oracle.com/cd/B13789_01/server.101/b10759/functions097.htm" rel="nofollow">http://docs.oracle.com/cd/B13789_01/server.101/b10759/functions097.htm</a> &#8211; mentione explicitly<br />
that there is &#8220;no restrictions on the type or length of data&#8221;, so I tested it on LONG&#8217;s too.<br />
And indeed&#8230; no problem at all.</p>
<p>Here is the the changed code, using the ORA_HASH function now: </p>
<p><code><br />
SQL&gt; set linesize 300 pagesize 0 heading off<br />
SQL&gt; select text from user_source where type='FUNCTION' and name ='DIFF_TABLES' order by line;<br />
FUNCTION Diff_Tables<br />
    ( P_name_tab1   VARCHAR2<br />
    , P_name_tab2   VARCHAR2<br />
    , P_owner_tab1  VARCHAR2 := USER<br />
    , P_owner_tab2  VARCHAR2 := USER )<br />
  RETURN PLS_INTEGER<br />
IS</p>
<p>  v_tab1   VARCHAR2(100)  := UPPER(TRIM(P_owner_tab1||'.'||P_name_tab1));<br />
  v_tab2   VARCHAR2(100)  := UPPER(TRIM(P_owner_tab2||'.'||P_name_tab2));<br />
  v_clist  VARCHAR2(4000) := NULL;<br />
  v_col    VARCHAR2(100);<br />
  cntr     PLS_INTEGER := 0;<br />
  cnt1     NUMBER := 0;<br />
  cnt2     NUMBER := 0;<br />
  v_ret    PLS_INTEGER := 0;</p>
<p>BEGIN</p>
<p>-- setup the column list<br />
  for x in ( select column_name<br />
                  , data_type<br />
             from dba_tab_columns<br />
             where owner||'.'||table_name = v_tab1<br />
             order by column_id )<br />
  loop<br />
    cntr := cntr + 1;<br />
    if x.data_type in ('CLOB','BLOB','LONG') then<br />
      v_col := 'ORA_HASH('||x.column_name||')';<br />
--      v_col := 'DBMS_LOB.SUBSTR('||x.column_name||',2000), DBMS_LOB.GETLENGTH('||x.column_name||')';<br />
    else<br />
      v_col := x.column_name;<br />
    end if;<br />
    if cntr != 1 then<br />
      v_col := ','||v_col;<br />
    end if;<br />
    v_clist := v_clist||v_col;<br />
  end loop;</p>
<p>-- compare<br />
  EXECUTE IMMEDIATE 'select count(*) from ( select '||v_clist||' from '||v_tab1||' minus select '||v_clist||' from '||v_tab2||' )' INTO cnt1;<br />
  EXECUTE IMMEDIATE 'select count(*) from ( select '||v_clist||' from '||v_tab2||' minus select '||v_clist||' from '||v_tab1||' )' INTO cnt2;</p>
<p>-- return 0 if tables match, and 1 if tables differ.<br />
  if (cnt1+cnt2) &gt; 0 then<br />
    v_ret := 1;<br />
  end if;</p>
<p>  return v_ret;</p>
<p>END Diff_Tables;</p>
<p>50 rows selected.</p>
<p>SQL&gt;<br />
</code></p>
]]></content:encoded>
	</item>
</channel>
</rss>
