2013-05-17 47 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