串联太长
Concatenation Too Long
说我有这个 table:
ID|Col1|Col2|Col3
1|Text that has 4000 chars|Text2 that has 4000 chars|Text3 that has 4000 chars
2|Text4 that has 4000 chars|Text5 that has 4000 chars|Text6 that has 4000 chars
3|Text7 that has 4000 chars|Text8 that has 4000 chars|Text9 that has 4000 chars
我是这样使用 listagg 的:
SELECT id,
listagg(col1||col2||col3, ',') within group (order by id)
FROM table;
我遇到了错误:
ORA-01489: result of string concatenation is too long
经过研究,我发现使用 xmlagg 可以解决问题 (link),但后来意识到真正的问题在于 col1、col2 和 col3 的串联,因为它仅限于 4000 个字符,所以做 xmlagg 仍然会 return 相同的错误。
有人解决这个问题了吗?或者没有解决方法? (link)
更新:
我更新了 table 上的样本值只是为了清楚(让 Kumar 先生理解),我的预期输出应该是这样的:
ID | Agg
1 | Text that has 4000 charsText2 that has 4000 charsText3 that has 4000 chars
2 | Text4 that has 4000 charsText5 that has 4000 charsText6 that has 4000 chars
3 | Text7 that has 4000 charsText8 that has 4000 charsText9 that has 4000 chars
这显然行不通。
你可以做得更简单,因为 Oracle 不久前引入了 SQL Semantics and LOBs。
SELECT ID, TO_CLOB(col1) || col2 || col3 AS very_long_text
FROM TABLE;
||
运算符的第一个元素必须是 CLOB
,然后才有效。
我终于让它工作了。我所做的是在连接列之前聚合列,按照 Kumar 先生的建议对其进行分组,然后再次聚合它们以修复排序。方法如下:
WITH agg_tbl AS
(
SELECT id,
rtrim(xmlagg(xmlelement(e,col1,',').extract('//text()').GetClobVal(),',')||rtrim(xmlagg(xmlelement(e,col1,',').extract('//text()').GetClobVal(),',')||rtrim(xmlagg(xmlelement(e,col1,',').extract('//text()').GetClobVal(),',') long_text
FROM table
GROUP BY col1
)
SELECT rtrim(xmlagg(xmlelement(e,long_text,chr(13)).extract('//text()').GetClobVal(),',') agg_value
FROM agg_tbl;
所以不是这个:
agg_value
Text that has 4000 charsText4 that has 4000 charsText7 that has 4000 chars
Text2 that has 4000 charsText5 that has 4000 charsText8 that has 4000 chars
Text3 that has 4000 charsText6 that has 4000 charsText9 that has 4000 chars
我现在得到了我想要的结果:
agg_value
Text that has 4000 charsText2 that has 4000 charsText3 that has 4000 chars
Text4 that has 4000 charsText5 that has 4000 charsText6 that has 4000 chars
Text7 that has 4000 charsText8 that has 4000 charsText9 that has 4000 chars
说我有这个 table:
ID|Col1|Col2|Col3
1|Text that has 4000 chars|Text2 that has 4000 chars|Text3 that has 4000 chars
2|Text4 that has 4000 chars|Text5 that has 4000 chars|Text6 that has 4000 chars
3|Text7 that has 4000 chars|Text8 that has 4000 chars|Text9 that has 4000 chars
我是这样使用 listagg 的:
SELECT id,
listagg(col1||col2||col3, ',') within group (order by id)
FROM table;
我遇到了错误:
ORA-01489: result of string concatenation is too long
经过研究,我发现使用 xmlagg 可以解决问题 (link),但后来意识到真正的问题在于 col1、col2 和 col3 的串联,因为它仅限于 4000 个字符,所以做 xmlagg 仍然会 return 相同的错误。
有人解决这个问题了吗?或者没有解决方法? (link)
更新:
我更新了 table 上的样本值只是为了清楚(让 Kumar 先生理解),我的预期输出应该是这样的:
ID | Agg
1 | Text that has 4000 charsText2 that has 4000 charsText3 that has 4000 chars
2 | Text4 that has 4000 charsText5 that has 4000 charsText6 that has 4000 chars
3 | Text7 that has 4000 charsText8 that has 4000 charsText9 that has 4000 chars
这显然行不通。
你可以做得更简单,因为 Oracle 不久前引入了 SQL Semantics and LOBs。
SELECT ID, TO_CLOB(col1) || col2 || col3 AS very_long_text
FROM TABLE;
||
运算符的第一个元素必须是 CLOB
,然后才有效。
我终于让它工作了。我所做的是在连接列之前聚合列,按照 Kumar 先生的建议对其进行分组,然后再次聚合它们以修复排序。方法如下:
WITH agg_tbl AS
(
SELECT id,
rtrim(xmlagg(xmlelement(e,col1,',').extract('//text()').GetClobVal(),',')||rtrim(xmlagg(xmlelement(e,col1,',').extract('//text()').GetClobVal(),',')||rtrim(xmlagg(xmlelement(e,col1,',').extract('//text()').GetClobVal(),',') long_text
FROM table
GROUP BY col1
)
SELECT rtrim(xmlagg(xmlelement(e,long_text,chr(13)).extract('//text()').GetClobVal(),',') agg_value
FROM agg_tbl;
所以不是这个:
agg_value
Text that has 4000 charsText4 that has 4000 charsText7 that has 4000 chars
Text2 that has 4000 charsText5 that has 4000 charsText8 that has 4000 chars
Text3 that has 4000 charsText6 that has 4000 charsText9 that has 4000 chars
我现在得到了我想要的结果:
agg_value
Text that has 4000 charsText2 that has 4000 charsText3 that has 4000 chars
Text4 that has 4000 charsText5 that has 4000 charsText6 that has 4000 chars
Text7 that has 4000 charsText8 that has 4000 charsText9 that has 4000 chars