Skip to Main Content
  • Questions
  • How to use varray type in where_clause of select statements?

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, minnie.

Asked: June 13, 2000 - 11:10 am UTC

Last updated: February 18, 2007 - 8:51 am UTC

Version: Oracle 8i 8.1.5

Viewed 1000+ times

You Asked

Hi,Tom
If I have a table including a column which is a varry type,

such as
create table myarray as varray(5) of number(10);
create table mytest(col1 number,col2 myarray)
insert into table mytest(1,myarray(1,2,3,4,5));

I try to use the values of varray type column as condition in where_clause like
"select * from mytest where col2=myarray(1,2,3,4,5);",
but I failed . How I can do









and Tom said...

From the PLSQL reference:

<quote>
Comparing Whole Collections

Nested tables and varrays can be atomically null, so they can be tested for nullity, as the following example shows:

DECLARE
TYPE Staff IS TABLE OF Employee;
members Staff;
BEGIN
...
IF members IS NULL THEN ... -- condition yields TRUE;
END;

However, collections cannot be compared for equality or inequality. For instance, the following IF condition is illegal:

DECLARE
TYPE Clientele IS TABLE OF Customer;
group1 Clientele := Clientele(...);
group2 Clientele := Clientele(...);
BEGIN
...
IF group1 = group2 THEN -- causes compilation error
...
END IF;
END;

This restriction also applies to implicit comparisons. For example, collections cannot appear in a DISTINCT, GROUP BY, or ORDER BY list.

</quote>

So, you need to use an OBJECT type to do this and, much like you would in Java or C++, you must create an "operator" to do the comparision -- Just as in Java you have to use:

stringVariable.isEqual( "some other string" )

we must use

objectCol.isEqual( some other object instance )

Here is a small example:

ops$tkyte@8i> create type myarray as varray(5) of number(10);
2 /
Type created.

ops$tkyte@8i> create type myObject as object
2 ( array myArray,
3 member function isEqual( p_other in myArray default null)
return number
4 )
5 /

Type created.

ops$tkyte@8i>
ops$tkyte@8i> create type body myObject
2 as
3 member function isEqual( p_other in myArray )
return number
4 is
5 begin
6 if ( self.array.count <> p_other.count )
7 then
8 return 0;
9 end if;
10
11 for i in 1 .. self.array.count
12 loop
13 if ( self.array(i) <> p_other(i) )
14 then
15 return 0;
16 end if;
17 end loop;
18 return 1;
19 end;
20 end;
21 /

Type body created.

ops$tkyte@8i> create table mytest(col1 number,col2 myObject)
2 /

Table created.

ops$tkyte@8i> insert into mytest
values ( 1, myObject( myarray(1,2,3,4,5) ) )
2 /

1 row created.

ops$tkyte@8i> select t.col2.array Array from mytest T
2 /

ARRAY
-------------------------
MYARRAY(1, 2, 3, 4, 5)

ops$tkyte@8i> select t.col1, t.col2.array array
2 from mytest t
3 where t.col2 = myobject( myarray(1,2,3,4,5) )
4 /

no rows selected

No data found, object1 <> object2...

ops$tkyte@8i>
ops$tkyte@8i> select t.col1, t.col2.array array
2 from mytest T
3 where t.col2.isEqual( myArray(1,2,3,4,5) ) = 1
4 /

COL1 ARRAY
---------- -------------------------
1 MYARRAY(1, 2, 3, 4, 5)


But out compare works OK




Rating

  (4 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Looping Through Collection Elements (PRIOR and NEXT Methods)

A reader, February 22, 2004 - 8:49 am UTC

Hi

How can we compare current array element and previous?

something like

if l_array(i) = l_array(i-1) thn blah blah

is this possible?

Tom Kyte
February 22, 2004 - 9:40 am UTC

you just wrote the code, you got it.

why this does not work?

A reader, February 22, 2004 - 9:51 am UTC

declare
type array is table of varchar2(30);
las array := array('TEST', 'LALA');
begin
for i in 1..las.count loop
dbms_output.put_line(las(i));
dbms_output.put_line(las(i-1));
end loop;
end;
/


TEST
declare
*
ERROR at line 1:
ORA-06532: Subscript outside of limit
ORA-06512: at line 7

Tom Kyte
February 22, 2004 - 10:10 am UTC

there is no (0) element. you sort of have to start at "2" if you want to compare to the prior one in all cases -- there is nothing prior to "1"

Comparing 2 arrays

Peter Belter, August 26, 2004 - 5:21 pm UTC

Hi Tom,

I have a situation where I need to compare 2 arrays received as IN parameters. Therefore I modified your function:

1 function isEqual( a_array IN myArray,
2 b_array IN myArray )
3 return number
4 is
5 begin
6 if ( a_array.count <> b_array.count )
7 then
8 return 0;
9 end if;
10
11 for i in 1 .. a_array.count
12 loop
13 if ( a_array(i) <> b_array(i) )
14 then
15 return 0;
16 end if;
17 end loop;
18 return 1;
19 end;

This gives:
PLS-00306: wrong number or types of arguments in call to '!='



Tom Kyte
August 26, 2004 - 7:13 pm UTC

ops$tkyte@ORA9IR2> create or replace type myarray as varray(5) of number(10);
  2  /
 
Type created.
 
ops$tkyte@ORA9IR2> create or replace
  2    function isEqual( a_array IN myArray,
  3                b_array IN myArray )
  4              return number
  5      is
  6      begin
  7          if ( a_array.count <> b_array.count )
  8          then
  9              return 0;
 10          end if;
 11
 12          for i in 1 .. a_array.count
 13          loop
 14              if ( a_array(i) <> b_array(i) )
 15              then
 16                  return 0;
 17              end if;
 18          end loop;
 19          return 1;
 20      end;
 21  /
 
Function created.


Need a complete test case, not sure what you did.... 

how to increase upper bound

A reader, February 16, 2007 - 4:11 pm UTC

I am getting ora-06532 when I make changes to one of my existing procedures.

WHEN I SEE IT IN

select * from all_coll_types where lower(type_name) = lower('DESCRIPTIONS');

OWNER TYPE_NAME COLL_TYPE UPPER_BOUND ELEM_TYPE_MOD ELEM_TYPE_OWNER ELEM_TYPE_NAME LENGTH PRECISION SCALE CHARACTER_SET_NAME ELEM_STORAGE NULLS_STORED
SCOTT DESSCRIPTIONS VARYING ARRAY 7 SCOTT DESCRIPTION YES


How can we increase the upper_bound here.

Tom Kyte
February 18, 2007 - 8:51 am UTC

you create or replace the type with a new upper bound.