Search code examples
oraclecompareclob

Oracle comparing clobs in same row


I have a table that contains some columns and two CLOBS.

In some cases both the CLOBS contain the same exact values and in other cases they contain different values. or one or both CLOBS can be empty or NULl.

I created a function, which I would like to call to compare both CLOBS to determine if the values are 'SAME' or different.


CREATE or REPLACE FUNCTION HASH_SHA512 (
    psINPUT IN VARCHAR2
    ) RETURN VARCHAR2 AS
    rHash RAW (512);
    BEGIN
    rHash := DBMS_CRYPTO.HASH (TO_CLOB (psINPUT), 
dbms_crypto.HASH_SH512);
    RETURN (LOWER (RAWTOHEX (rHash)));
    END HASH_SHA512;
/



CREATE table table_x(
seq_num integer  GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL,
val NUMBER, 
clob1 CLOB,
clob2 CLOB);


insert into table_x (val, clob1, clob2) values (1,'aaaaaaaaaa','aaaaaaaaaa');

insert into table_x (val, clob1, clob2) values (1,'aaaaa','aaaaaaaaaa');

insert into table_x (val, clob1, clob2) values (2,'Xaaaaaaaaa','aaaaaaaaaa');

Expected output 

SEQ_NUM    VAL    CLOB1    CLOB2
1    1    aaaaaaaaaa    aaaaaaaaaa  SAME
2    1    aaaaa    aaaaaaaaaa DIFFERENT 
3    2     Xaaaaaaaaa    aaaaaaaaaa DIFFERENT 

Based on the output of the above query if the SHA512 output shows the difference to be the same I want to INSERT 1 row into the new table below. If the output is different, I want to INSERT 2 rows into the table below.

CREATE table table_z(
seq_num integer  GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL,
val NUMBER, 
hash_val VARCHAR2(1000) not NULL PRIMARY KEY, 
clob_val CLOB);


Solution

  • It does not make very much sense to write your own function to compare two LOBs since Oracle already has a COMPARE function in the DBMS_LOB package. It can easily be leveraged in your query like this:

    SELECT x.*,
           CASE DBMS_LOB.compare (x.clob1, x.clob2) WHEN 0 THEN 'SAME' ELSE 'DIFFERENT' END    AS comparison
      FROM table_x x;
    
       SEQ_NUM    VAL         CLOB1         CLOB2    COMPARISON
    __________ ______ _____________ _____________ _____________
             1      1 aaaaaaaaaa    aaaaaaaaaa    SAME
             2      1 aaaaa         aaaaaaaaaa    DIFFERENT
             3      2 Xaaaaaaaaa    aaaaaaaaaa    DIFFERENT
    

    To insert the different CLOBs into table_z you could use a SQL statement like this:

    INSERT INTO table_z (val, hash_val, clob_val)
        SELECT x1.val, DBMS_CRYPTO.HASH (x1.clob1, 6                          /*DBMS_CRYPTO.HASH_SH512*/
                                                    ), x1.clob1
          FROM table_x x1
        UNION ALL
        SELECT x2.val, DBMS_CRYPTO.HASH (x2.clob2, 6                          /*DBMS_CRYPTO.HASH_SH512*/
                                                    ), x2.clob2
          FROM table_x x2
         WHERE DBMS_LOB.compare (x2.clob1, x2.clob2) <> 0;
    

    Currently, the PRIMARY KEY you have defined on table_z would prevent the sample records you provided from inserting because the same CLOB appears on multiple rows. You can either remove that primary key or add additional columns to the primary key to allow the data to be inserted.