8

目前我有以下查询:

SELECT 
    CASE 
       WHEN ('[Param.3]' = 'SELECTED')
          THEN (SELECT RTRIM(XMLELEMENT("Rowset", XMLAGG(RW.R ORDER BY RW."ID")), ' ' ) AS Orders
                FROM TMTABLE UL, XMLTABLE('Rowsets/Rowset/Row' PASSING UL.TEXT COLUMNS "ID" NUMBER(19) PATH 'ID', R xmltype path '.') AS RW
                WHERE ID BETWEEN '[Param.1]' and '[Param.2]')
       WHEN ('[Param.3]' = 'ALL' )
          THEN (SELECT RTRIM(XMLELEMENT("Rowset", XMLAGG(RW.R ORDER BY RW."ID")) , ' ' ) AS Orders
                FROM TMTABLE UL, XMLTABLE('Rowsets/Rowset/Row' PASSING UL.TEXT COLUMNS "ID" NUMBER(19) PATH 'ID', R xmltype path '.') AS RW)
    END AS Orders
FROM 
    dual

如果使用 XML AGG 将少量 XML 行合并为单行,则此查询工作正常。但如果要合并的 XML 行数较高,则此查询将引发以下错误:

ORA-19011: 字符串缓冲区太小

我需要进行哪些更改才能完成这项工作?

4

2 回答 2

17

您需要.getClobVal()在 RTRIM 之前添加到您的 XMLType 结果。

XMLAGG 可以很好地处理大量数据。并且 TRIM 可以很好地与 CLOB 配合使用。但是当您将它们放在一起时,Oracle 会尝试将 XMLType 转换为 VARCHAR2 而不是 CLOB。

例子:

create or replace function test_function return clob is
    v_clob clob;
begin
    v_clob := v_clob || lpad('a', 4000, 'a');
    v_clob := v_clob || lpad('b', 4000, 'b');
    return v_clob;
end;
/

--Works fine, returns an XMLType
select xmlagg(xmlelement("asdf", test_function)) from dual;

--Works fine, returns a CLOB
select trim(test_function) from dual;

--ORA-19011: Character string buffer too small
select trim(xmlagg(xmlelement("asdf", test_function))) from dual;

--Works
select trim(xmlagg(xmlelement("asdf", test_function)).getClobVal()) from dual;
于 2012-11-09T05:34:17.100 回答
2

您需要添加getClobVal()并且还需要添加,rtrim()因为它将在结果末尾返回分隔符。

SELECT RTRIM(XMLAGG(XMLELEMENT(E,colname,',').EXTRACT('//text()') ORDER BY colname).GetClobVal(),',')
  FROM tablename;
于 2015-03-13T10:01:23.893 回答