2013-04-24 18 views
5

Sto utilizzando la raccolta in un blocco di codice Oracle perché non esiste alcuna variabile di tabella (come in MS SQL Server).Raccolta Oracle nella clausola where

DECLARE 
    TYPE I_NAME IS TABLE OF NVARCHAR2(512);  
    I_ITEMNAME  I_NAME := I_NAME(); 
BEGIN 

Sto usando "MASSA raccoglierli in I_ITEMNAME" da riempire di raccolta.
Desidero utilizzare questa raccolta nella clausola WHERE in una query SELECT ma non in grado di trovare il metodo per farlo. Attualmente io e utilizzando il ciclo FOR e ricevo gli articoli uno per uno.
Come posso usare collezione direttamente in WHERE clausola qualcosa come

SELECT * FROM WHERE TBL COL IN I_ITEMNAME?

Grazie,

risposta

9

Non è possibile utilizzare una collezione dichiarato localmente in una clausola 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 

ma è possibile se è dichiarata a livello di schema, in sostanza, in modo che SQL conosce il tipo, non solo 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. 

Si può anche unire le table costrutto piuttosto che utilizzare una su bquery:

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

Non so bene cosa tu sia dong. (Se non utilizzi la raccolta per qualcos'altro, staresti meglio solo unendo i dati grezzi, ma presumo che la raccolta sia lì per un motivo).


Come @haki menzionato nei commenti, si può anche fare:

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

... finché i_name e la colonna si sta confrontando con are the same type. Nel mio esempio trova zero righe perché sto cercando di confrontare nvarchar2 con varchar2, ma troverei una corrispondenza se ridefinito i_name come varchar2(512). Nel tuo caso presumibilmente tab.col è nvarchar2 comunque.

+2

+1 Penso che puoi anche usarlo come questo 'select count (*) da all_tables dove membro proprietario di (i_itemname)'. – haki

+0

@haki - bello, non penso di averlo mai usato. Per il mio esempio non trova corrispondenze [perché il tipo non corrisponde] (http://docs.oracle.com/cd/E11882_01/server.112/e26088/conditions006.htm#sthref1966) - Ho 'i_type' come 'nvarchar2' ma' owner' è 'varchar2', ma è pulito se' i_type' viene ridefinito per corrispondere. (L'ho aggiunto alla mia risposta, ma se pubblichi la tua risposta con quella la rimuoverò, non tentando di assumermi il merito!) –