在 oracle 中使用 listagg 时出错“字符串连接太长”

Posted

技术标签:

【中文标题】在 oracle 中使用 listagg 时出错“字符串连接太长”【英文标题】:Error while using listagg in oracle "STRING concatenation too long" 【发布时间】:2020-03-19 10:37:34 【问题描述】:

我有一个像 temp_a 这样的表:

acc ai_tab   where
A   B        QQQQ
A   B        RRRR
C   D        SSSS
C   D        TTTT

where 列存储的字符串过大。所以,我的预期输出是

acc ai_tab where 
A   B      QQQQ RRRR
C   D      SSSS TTTT

我尝试使用:

 select acc,ai_tab,LISTAGG(WHERE,'') WITHIN GROUP ORDER BY (acc) "where_cond2" from temp_a
group by acc,ai_tab;

我得到的错误是:

ORA-01489 :result of string concatenation is too long.

我搜索了这个类似的问题,它说也使用 XMLCLOB,但它不起作用?我们可以使用函数来获取它还是有任何其他方法?

【问题讨论】:

如果您使用的是 12cR2,您可以使用溢出选项来优雅地处理问题。它会截断输出,但至少您的查询不会引发错误。 Find out more。当您说“XMLCLOB [is] not working”时会发生什么?你有错误吗?如果有,是什么? 但我不需要截断数据。我需要这些字符串的所有值 你能通过显示 @APC 的例子来帮助我吗 【参考方案1】:

这是一个示例,它显示了您可能会使用的两个选项;由于listagg 失败,请改用xmlagg

SQL> SELECT RTRIM (
  2            XMLAGG (XMLELEMENT (e, ename || ' ') ORDER BY empno).EXTRACT (
  3               '//text()'),
  4            ', ')
  5            employees_1,
  6         --
  7         LISTAGG (ename, ' ') WITHIN GROUP (ORDER BY empno) employees_2
  8    FROM emp
  9   WHERE deptno = 10;

EMPLOYEES_1                    EMPLOYEES_2
------------------------------ ------------------------------
CLARK KING MILLER              CLARK KING MILLER

SQL>

【讨论】:

我不需要逗号我需要空格 是什么阻止你用空格替换逗号? 我替换但所有值都为空 我在 ' ' 中的所有数据都以 &apos 的形式出现。为什么会这样? 对我来说一切正常;我修改了示例以用空格分隔字符串。至于你的另一个问题:样本数据真的是你发布的,还是别的什么?【参考方案2】:

同意 Littlefoot 的解决方案。 或者,您也许可以编写自己的函数。我在下面包含了一个示例。 注意:我没有用你的数据对此进行测试,所以不确定它的性能如何

    SQL> create table foo as
         select 'A' acc, 'B' ai_tab, 'QQQQ' where_column from dual union all
         select 'A','B','RRRR' from dual union all
         select 'C','D','SSSS' from dual union all
         select 'C','D','TTTT' from dual;

    Table created.

    SQL> select * from foo;

    ACC AI_TAB WHERE_COLUMN
    --  --     ----
    A   B      QQQQ
    A   B      RRRR
    C   D      SSSS
    C   D      TTTT

    SQL> create or replace function str_concat (
             p_acc       in  foo.acc%type,
             p_ai_tab    in  foo.ai_tab%type
             )
         return clob
         is
             l_concat  clob;
         begin
         for o in ( 
                 select where_column from foo where acc = p_acc and ai_tab =  p_ai_tab  
             ) loop
                     l_concat := l_concat || ' ' || o.where_column;
                 end loop;
             return ltrim(l_concat, ' ');
         end;
         /

    Function created.

    SQL> select acc, ai_tab, where_column from (
         select acc, ai_tab, str_concat(acc, ai_tab) where_column, row_number() over (partition by acc, ai_tab order by null)
         ) where rn = 1;

    ACC AI_TAB  WHERE_COLUMN
    --  --      ----
    A   B       QQQQ RRRR
    C   D       SSSS TTTT

【讨论】:

以上是关于在 oracle 中使用 listagg 时出错“字符串连接太长”的主要内容,如果未能解决你的问题,请参考以下文章

oracle行转列,列转行函数的使用(listagg,xmlagg)

oracle函数listagg的使用说明

用listagg怎么替代这个写法

Oracle Database 19c 中的 LISTAGG DISTINCT

oracle 10g中listagg的替代品

oracle listagg的 截取长度限制有没有啥方法解决