如何连接字符串?

发布于 2024-12-26 03:14:55 字数 272 浏览 2 评论 0原文

我使用的是 Oracle 10g,表结构如下: ID, 我想按 id分组

并连接段落。每个段落可能有 1500 个字符或更多。

当我尝试 wm_concat 函数时,它抱怨字符串缓冲区太小。我实际上尝试了 Oracle 网站上的许多示例,但它们都失败了,并出现字符串缓冲区太小的错误。

select id, wm_concat(paragraph) from paragraphs group by id

我该如何解决这个问题?

I'm on Oracle 10g and have the following table structure:
id,
paragraph

I want to group by id and concatenate the paragraphs. Each paragraph maybe 1500 characters or more.

When I try the wm_concat function, it complains that the string buffer is too small. I actually tried many of the examples on Oracle's website and they all fail with the error the string buffer is too small.

select id, wm_concat(paragraph) from paragraphs group by id

how do I solve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

却一份温柔 2025-01-02 03:14:55

所以,我猜测错误是 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.

至于解决,恐怕解决不了。一旦你达到了这个极限,就这样了。您必须找到一种不同的聚合方式,或者问问自己是否真的需要这样做。

So, I'm guessing the error is ORA-06502 and I can see how you might think that this doesn't apply to you in this situation.

However, this is the fault of wm_concat. This is a function and is constrained by Oracle's maximum varchar length in PL\SQL of 32,767 and 4,000 in standard SQL. Unfortunately, I assume, because of the way that wm_concat works or because of any lower constraints within the function or because you're using it in a select you can't get anywhere near the upper limit.

There is another option, stragg, Tom Kyte's string aggregate function. If we look at the following comparison between the two you'll see that they perform almost identically and that the limit of both is a length of around 4,000, i.e. the standard SQL maximum. stragg is slightly faster, probably due to caching.

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.

As for solving it, I'm afraid you can't. Once you hit that limit that's it. You'll have to find a different way of doing your aggregations or ask yourself if you really need to.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文