【问题标题】:Oracle collection in where clause在 where 子句中的 Oracle 集合
【发布时间】:2013-04-24 06:53:50
【问题描述】:

我在 oracle 代码块中使用集合,因为没有表变量(如在 MS SQL Server 中)。

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

我正在使用“BULK COLLECT INTO I_ITEMNAME”来填充收藏。
我想在 SELECT 查询的 WHERE 子句中使用此集合,但找不到执行此操作的方法。目前我正在使用 FOR 循环并一项一项地获取项目。
如何在 WHERE 子句中直接使用集合,例如

SELECT * FROM TBL WHERE COL IN I_ITEMNAME?

谢谢,

【问题讨论】:

    标签: oracle collections


    【解决方案1】:

    您不能在 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
    

    但如果它是在模式级别声明的,则可以,本质上是让 SQL 知道类型,而不仅仅是 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.
    

    您也可以加入table 构造而不是使用子查询:

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

    我不太清楚你是什么东东。 (如果您没有将集合用于其他任何用途,最好只加入原始数据,但我认为集合的存在是有原因的)。


    正如@haki 在 cmets 中提到的,你也可以这样做:

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

    ...只要i_name 和您要与are the same type 比较的列。在我的示例中,它找到了零行,因为我试图将nvarchar2varchar2 进行比较,但如果将i_name 重新定义为varchar2(512),则会找到匹配项。在你的情况下,大概tab.colnvarchar2 反正。

    【讨论】:

    • +1 我觉得你也可以这样使用select count(*) from all_tables where owner member of (i_itemname)
    • @haki - 很好,我想我从来没有使用过它。对于我的示例,它找不到匹配 because the type doesn't match - 我有 i_type 作为 nvarchar2ownervarchar2,但如果 i_type 被重新定义以匹配,那就很好了。 (我已将其添加到我的答案中,但如果您发布自己的答案,我会将其删除;不要试图获得荣誉!)
    • 这是一个完美的解释,为了获得更好的性能 - 如果您的集合大小会很大 - 最好将类型索引 - 例如 - 创建类型 i_name 是 PLS_INTEGER 的数字索引表;
    猜你喜欢
    • 1970-01-01
    • 2018-02-12
    • 2017-11-12
    • 2010-12-18
    • 2011-10-08
    • 2017-12-21
    • 1970-01-01
    • 1970-01-01
    • 2019-03-15
    相关资源
    最近更新 更多