Oracle collection in where clause

后端 未结 1 1247
广开言路
广开言路 2020-12-10 06:15

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);          


        
相关标签:
1条回答
  • 2020-12-10 06:37

    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.

    0 讨论(0)
提交回复
热议问题