我在 Oracle 10g 上,具有以下表结构:id、paragraph
我想按 id 分组并连接段落。每个段落可能有 1500 个字符或更多。
当我尝试 wm_concat 函数时,它抱怨字符串缓冲区太小。我实际上尝试了 Oracle 网站上的许多示例,但它们都失败了,错误是字符串缓冲区太小。
select id, wm_concat(paragraph) from paragraphs group by id
我该如何解决?
我在 Oracle 10g 上,具有以下表结构:id、paragraph
我想按 id 分组并连接段落。每个段落可能有 1500 个字符或更多。
当我尝试 wm_concat 函数时,它抱怨字符串缓冲区太小。我实际上尝试了 Oracle 网站上的许多示例,但它们都失败了,错误是字符串缓冲区太小。
select id, wm_concat(paragraph) from paragraphs group by id
我该如何解决?
所以,我猜错误是ORA-06502
,我可以看到你可能认为这在这种情况下不适用于你。
然而,这是 的错wm_concat
。这是一个函数,受 Oracle 在 PL\SQL 中的最大 varchar 长度为 32,767 和在标准 SQL 中为 4,000 的限制。不幸的是,我认为,由于 wm_concat 的工作方式或由于函数内的任何较低约束,或者因为您在选择中使用它,您无法接近上限。
还有另一种选择,stragg
Tom Kyte 的字符串聚合函数。如果我们看一下两者之间的以下比较,您会发现它们的性能几乎相同,并且两者的限制是大约 4,000 的长度,即标准 SQL 最大值。stragg
稍微快一点,可能是由于缓存。
SQL> set serveroutput on
SQL>
SQL> create table tmp_test ( a varchar2(30) );
Table created.
SQL> insert into tmp_test
2 select object_name
3 from all_objects
4 ;
81219 rows created.
SQL> commit ;
Commit complete.
SQL>
SQL> declare
2
3 i integer := 1;
4 k number(10);
5 v_stragg varchar2(32767);
6 v_test varchar2(32767) := '';
7 start_time timestamp;
8
9 begin
10
11 select count(*)
12 into k
13 from tmp_test;
14
15 for i in 1 .. k loop
16 start_time := systimestamp;
17 begin
18
19 select wm_concat(a) into v_test
20 from tmp_test
21 where rownum < i;
22
23 exception when others then
24 dbms_output.put_line('wm_concat: ' || length(v_test));
25 dbms_output.put_line(systimestamp - start_time);
26 exit;
27 end;
28 end loop;
29
30 for i in 1 .. k loop
31 start_time := systimestamp;
32
33 select stragg(a) into v_test
34 from tmp_test
35 where rownum < i;
36
37 if v_test = 'OVERFLOW' then
38 dbms_output.put_line('stragg: ' || length(v_stragg));
39 dbms_output.put_line(systimestamp - start_time);
40 exit;
41 else v_stragg := v_test;
42 end if;
43 end loop;
44 end;
45 /
wm_concat: 3976
+000000000 00:00:00.005886000
stragg: 3976
+000000000 00:00:00.005707000
PL/SQL procedure successfully completed.
至于解决,恐怕你解决不了。一旦你达到了这个极限,就是这样。您必须找到一种不同的方式来进行聚合,或者问问自己是否真的需要。