2013-02-13 28 views
11

長すぎる:LISTAGG機能とORA-01489:私は次のクエリを実行すると、文字列連結の結果が

Select 
    tm.product_id, 
    listagg(tm.book_id || '(' || tm.score || ')',',') 
    within group (order by tm.product_id) as matches 
from 
    tl_product_match tm 
where 
    tm.book_id is not null 
group by 
    tm.product_id 

Oracleは、次のエラーを返します。

ORA-01489: result of string concatenation is too long 

は、私が知っている理由はそれということlistagg関数が、サポートされていない4000文字を超える値を連結しようとしていることが原因です。

ここに記載された代替の例 - http://www.oracle-base.com/articles/misc/string-aggregation-techniques.phpを見ましたが、それらはすべて関数またはプロシージャを使用する必要があります。

標準のJDBCを使用して関数またはストアドプロシージャを呼び出して値を読み取る必要がなく、純粋なSQLのソリューションがありますか?

私が持っている他の難しさは、私が見たほとんどの文字列集約の例は、値をそのまま読み込む方法の例を示しています。私の例では、まず値を変更しています(つまり、2つの列を集約しています)。

答えて

0

I have seen the alternative example described here - http://www.oracle-base.com/articles/misc/string-aggregation-techniques.php but they all require the use of functions or procedure.

いいえいいえ。下にスクロールすると、pl/sqlを必要としないオプションがいくつか表示されます。

+2

これらのソリューションのいずれもがCLOBを返すことをサポートし、PL/SQLオブジェクトの作成を必要としないことは明らかです。どちらの基準を満たしていると思われるページのオプションはどれですか? –

6

xml関数を使用してCLOBを返すことができます。 JDBCはそれでうまくいくはずです。

select tm.product_id, 
     rtrim(extract(xmlagg(xmlelement(e, tm.book_id || '(' || tm.score || '),')), 
       '/E/text()').getclobval(), ',') 
    from tl_product_match tm 
where tm.book_id is not null 
group by tm.product_id; 

例:ネストされたテーブルを使用しないのはなぜhttp://sqlfiddle.com/#!4/083a2/1

+0

私はXML版を試しましたが、かなり遅いです。それは通常、純粋なSQLよりも遅いですか? – ziggy

+0

listaggを使用した元のクエリは0.872秒かかりますが、XMLバージョンは4.461秒です – ziggy

+0

@ziggy xmlに関わる必要があるため遅くなる可能性があります。また、あなたのタイミングはlistaggがクラッシュしなかった同じセットにあったと仮定しています:) – DazzaL

3

set echo on; 
set display on; 
set linesize 200; 

drop table testA; 
create table testA 
(
col1 number, 
col2 varchar2(50) 
); 

drop table testB; 
create table testB 
(
col1 number, 
col2 varchar2(50) 
); 

create or replace type t_vchar_tab as table of varchar2(50); 

insert into testA values (1,'A'); 
insert into testA values (2,'B'); 

insert into testB values (1,'X'); 
insert into testB values (1,'Y'); 
insert into testB values (1,'Z'); 
commit; 

-- select all related testB.col2 values in a nested table for each testA.col1 value 
select a.col1, 
cast(multiset(select b.col2 from testB b where b.col1 = a.col1 order by b.col2) as t_vchar_tab) as testB_vals 
from testA a; 

-- test size > 4000 
insert into testB 
select 2 as col1, substr((object_name || object_type), 1, 50) as col2 
from all_objects; 
commit; 

-- select all related testB.col2 values in a nested table for each testA.col1 value 
select a.col1, 
cast(multiset(select b.col2 from testB b where b.col1 = a.col1 order by b.col2) as t_vchar_tab) as testB_vals 
from testA a; 

私はJavaの専門家だが、これはいくつかの時間を回避されていると私はJavaは、ネストされたテーブルから値を引くことができます確信しています。そして、もう一方の端で区切られた文字列をトークン化する必要はありません。

+0

これはすばらしい提案です –

関連する問題