Oracle
 sql >> Base de données >  >> RDS >> Oracle

Collection Oracle dans la clause where

Vous ne pouvez pas utiliser une collection déclarée localement dans une clause SQL :

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

Mais vous pouvez le faire s'il est déclaré au niveau du schéma, essentiellement pour que SQL connaisse le type, pas seulement 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.

Vous pouvez également rejoindre la table construire plutôt qu'utiliser une sous-requête :

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

Je ne suis pas tout à fait clair ce que vous êtes dong cependant. (Si vous n'utilisez pas la collection pour autre chose, vous feriez mieux de simplement joindre les données brutes, mais je suppose que la collection est là pour une raison).

Comme @haki l'a mentionné dans les commentaires, vous pouvez également faire :

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

... tant que i_name et la colonne que vous comparez avec sont les mêmes taper . Dans mon exemple, il ne trouve aucune ligne car j'essaie de comparer nvarchar2 avec varchar2 , mais trouverait une correspondance si redéfini i_name comme varchar2(512) . Dans votre cas, probablement tab.col est nvarchar2 de toute façon.