How to compare complex collections in Oracle?
Let us say I have two table types (tables of object types) that I want to compare for equality...
The object types have multiple fields, say, an integer, varchar2, and date.
I have seen examples where people use MULTISET EXCEPT in order to effectively do a MINUS on two tables of INTEGER.
But this does not work with two tables of complex object types.
Also I have seen mentioned the use of MAP MEMBER FUNCTION in order to make complex collections work when using the SET operator, but no mention of MULTISET functionality.
The current way I am comparing for equality is to take table type 1 (TT1) and table type 2 (TT2) and say they are equal if TT1 MINUS TT2 = 0 AND TT2 MINUS TT1 = 0. But here I am just selecting the PK from both tables for the MINUS, I would also like to be able to compare more than one field.
I am hoping MULTISET is faster?
Yes, you can use a MAP MEMBER FUNCTION to support comparing nested tables of types.
--#1: Create object create or replace type type1 is object ( a integer, b varchar2(100), c date, map member function compare return raw ); / --#2: Create map function for comparisons. --Returns the concatenated RAW of all attributes. --Note that this will consider NULLs to be equal! create or replace type body type1 as map member function compare return raw is begin return utl_raw.cast_to_raw(to_char(a))|| utl_raw.cast_to_raw(b)|| utl_raw.cast_to_raw(to_char(c, 'DD-MON-YYYY HH24:MI:SS')); end; end; / --#3: Create nested table of the types create or replace type type1_nt is table of type1; / --#4: Compare. --You could use MULTISET, but it's easier to use regular operators like "<>" "and =". declare tt1 type1_nt := type1_nt(type1(0, 'A', date '2000-01-01'), type1(0, 'A', date '2000-01-01')); tt2 type1_nt := type1_nt(type1(0, 'B', date '2000-01-01'), type1(0, 'B', date '2000-01-01')); tt3 type1_nt := type1_nt(type1(0, 'B', date '2000-01-01'), type1(0, 'B', date '2000-01-01')); begin if tt1 <> tt2 and tt2 = tt3 then dbms_output.put_line('Pass'); else dbms_output.put_line('Fail'); end if; end; /
I don't know if this would be faster than manually comparing each attribute. But I would guess the difference won't be significant.