2013-05-17 6 views
5

BULK COLLECTステートメントを使用しようとすると、エラーORA-00947: not enough valuesが返されます。オブジェクトの表にBULKを集める

サンプルスクリプト:

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

を...しかしunionは重複を識別して削除するには、暗黙的な順序付けを行いますので、とき実行ORA-22950: cannot ORDER objects without MAP or ORDER methodがスローされますので、代わりに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に取得し、次に "FOR .. LOOP(pipe_row(atReportRow))END LOOP;"を実行します。多分この部分も簡素化できますか? – xacinay

+1

@xacinay - 'bulk collect'ではなく。代わりにカーソルループとして実行することができます( 'for rec(select company_t()as comp ...)。ループパイプ行rec.comp;終了ループ;'または同様のものです。 –

+0

それはちょうどそれが動作する方法です: 'xの(選択..)パイプ行(company_t(x.Company、x.ClientCnt)))' 'のための新しい質問をしてください。私はちょうどそれがより簡単にすることができます、それは不思議だった。とにかく、現在の結果はかなりいいです、ありがとう! – xacinay