Oracle collection in where clause

collections, oracle

Solution

You can't use a locally declared collection in an SQL clause:

declare
    type i_name is table of nvarchar2(512);
    i_itemname i_name := i_name();
    c number;
begin
    select distinct owner bulk collect into i_itemname from all_objects;
    dbms_output.put_line(i_itemname.count);
    select count(*) into c
    from all_tables
    where owner in (select * from table(i_itemname));
    dbms_output.put_line(c);
end;
/

    where owner in (select * from table(i_itemname));
                                        *
ERROR at line 10:
ORA-06550: line 10, column 41:
PLS-00642: local collection types not allowed in SQL statements
ORA-06550: line 10, column 35:
PL/SQL: ORA-22905: cannot access rows from a non-nested table item
ORA-06550: line 8, column 5:
PL/SQL: SQL Statement ignored

But you can if it's declared at schema level, essentially so that SQL knows about the type, not just PL/SQL:

create type i_name is table of nvarchar2(512);
/

Type created.

declare
    i_itemname i_name := i_name();      
    c number;
begin 
    select distinct owner bulk collect into i_itemname from all_objects;
    dbms_output.put_line(i_itemname.count);
    select count(*) into c from all_tables
    where owner in (select * from table(i_itemname));
    dbms_output.put_line(c);
end;
/

No errors.
18
128

PL/SQL procedure successfully completed.

You can also join the `table` construct rather than use a subquery:

...
    select count(*) into c
    from table(i_itemname) t
    join all_tables at on at.owner = t.column_value;
...

I'm not quite clear what you're dong though. (If you aren't using the collection for anything else, you'd be better off just joining the raw data, but I assume the collection is there for a reason).

As @haki mentioned in comments, you can also do:

...
    select count(*) into c
    from all_tables
    where owner member of (i_itemname);
...

... as long as `i_name` and the column you're comparing with are the same type. In my example it finds zero rows because I'm trying to compare `nvarchar2` with `varchar2`, but would find a match if redefined `i_name` as `varchar2(512)`. In your case presumably `tab.col` is `nvarchar2` anyway.

Problem

I am using collection in a oracle code block because there is no table variable(like in MS SQL Server). ``` DECLARE TYPE I_NAME IS TABLE OF NVARCHAR2(512); I_ITEMNAME I_NAME := I_NAME(); BEGIN ``` I am using "BULK COLLECT INTO I_ITEMNAME" to fill collection. I want to use this collection in WHERE clause in a SELECT query but not able to find method to do it. Currently i and using FOR loop and getting item one by one. How can i use collection directly in WHERE clause somethin like SELECT * FROM TBL WHERE COL IN I_ITEMNAME? Thank you,

Original source