2013-04-24 14 views
5

Używam kolekcji w bloku kodu Oracle, ponieważ nie ma zmiennej tabeli (jak w MS SQL Server).Kolekcja Oracle gdzie klauzula

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

Używam "BULK COLLECT INTA I_ITEMNAME" do wypełnienia kolekcji.
Chcę użyć tej kolekcji w klauzuli WHERE w kwerendzie SELECT, ale nie można znaleźć metody, aby to zrobić. Obecnie używam pętli FOR i otrzymuję przedmiot jeden po drugim.
Jak mogę wykorzystać kolekcję bezpośrednio w klauzuli WHERE Czegoś podobnego

select * from TBL GDZIE COL IN I_ITEMNAME?

Dziękuję

Odpowiedz

9

nie można używać lokalnie deklarowanej kolekcję w klauzuli 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 

ale można, jeśli jest zadeklarowane na poziomie schematu, w zasadzie tak, że SQL wie o rodzaj, nie tylko 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. 

można również dołączyć do table konstrukt zamiast użyć su bquery:

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

Nie jestem do końca pewien, o co chodzi. (Jeśli nie używasz tej kolekcji do niczego innego, lepiej byłoby po prostu dołączyć do surowych danych, ale zakładam, że kolekcja jest z jakiegoś powodu).


Jak @haki wspomniano w komentarzach, można również zrobić:

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

... tak długo, jak i_name a kolumna jesteś porównując z are the same type. W moim przykładzie znajduje zero wierszy, ponieważ próbuję porównać nvarchar2 z varchar2, ale znajdę dopasowanie, jeśli ponownie zdefiniowano i_name jako varchar2(512). W twoim przypadku prawdopodobnie tab.col jest w każdym razie nvarchar2.

+2

+1 Myślę, że możesz również użyć go w ten sposób: "wybierz liczbę (*) z all_tables, gdzie właściciel jest członkiem (i_itemname)". – haki

+0

@haki - miło, nie sądzę, żebym kiedykolwiek użył tego. Dla mojego przykładu nie znajdzie dopasowania [ponieważ typ nie pasuje] (http://docs.oracle.com/cd/E11882_01/server.112/e26088/conditions006.htm#sthref1966) - Mam 'i_type' jako 'nvarchar2' ale' owner' to 'varchar2', ale jest niezłe, jeśli' i_type' jest na nowo zdefiniowany. (Dodałem to do mojej odpowiedzi, ale jeśli zamieścisz własną odpowiedź, usuniemy ją, a nie próbuję wziąć kredyt!) –