2013-05-17 112 views
5

当试图使用BULK COLLECT声明时,我收到错误ORA-00947: not enough values批量收集到对象表中

一个示例脚本:

CREATE OR REPLACE 
TYPE company_t AS OBJECT ( 
    Company   VARCHAR2(30), 
    ClientCnt   INTEGER ); 
/

CREATE OR REPLACE 
TYPE company_set AS TABLE OF company_t;  
/

CREATE OR REPLACE 
FUNCTION piped_set (
    v_DateBegin IN DATE, 
    v_DateEnd IN DATE 
) 
return NUMBER /*company_set pipelined*/ as 
    v_buf company_t := company_t(NULL, NULL); 
    atReport company_set; 
    sql_stmt VARCHAR2(500) := ''; 
begin 

select * BULK COLLECT INTO atReport 
from (
    SELECT 'Descr1', 1 from dual 
    UNION 
    SELECT 'Descr2', 2 from dual) ; 

    return 1; 
end; 

在线路select * BULK COLLECT INTO atReport会出现错误。

直PL/SQL的工作方式很好(所以不需要提及它的解决方案)。将BULK COLLECT用于用户表类型是个问题。

回答

9

您的company_set对象的表格,您选择的是值,而不是由这些值组成的对象。这将编译:

select * BULK COLLECT INTO atReport 
from (
    SELECT company_t('Descr1', 1) from dual 
    UNION 
    SELECT company_t('Descr2', 2) from dual) ; 

...但在运行时将抛出ORA-22950: cannot ORDER objects without MAP or ORDER method因为union确实隐含顺序来识别并删除重复,所以使用union all代替:

select * BULK COLLECT INTO atReport 
from (
    SELECT company_t('Descr1', 1) from dual 
    UNION ALL 
    SELECT company_t('Descr2', 2) from dual) ; 
+0

感谢,@Alex,代码真的帮助!作为问题的延续,是否可以将批量插入的结果作为流水线函数结果传递?目前,我将结果导入atReport ant,然后执行“FOR .. LOOP(pipe_row(atReportRow))END LOOP;”。也许这部分也可以简化? – xacinay

+1

@xacinay - 不与'bulk collect';你可以将它作为一个游标循环来代替(对于rec in(选择company_t()作为comp ...)循环管道行rec.comp; end loop;'或者类似的,我认为性能会类似。请问一个新的问题,如果你尝试,并且不能使它工作。 –

+0

这就是它的工作方式:'在(选择..)管道行(company_t(x.Company,x.ClientCnt)))'中输入x。我只是想知道,它可以更简单。无论如何,目前的结果非常好,谢谢! – xacinay