我使用的是Oracle SQL Developer版本3.0.04。我尝试使用函数LISTAGG
将数据分组在一起。
CREATE TABLE FINAL_LOG AS
SELECT SESSION_DT, C_IP, CS_USER_AGENT,
listagg(WEB_LINK, ' ')
WITHIN GROUP(ORDER BY C_IP, CS_USER_AGENT) "WEB_LINKS"
FROM webviews
GROUP BY C_IP, CS_USER_AGENT, SESSION_DT
ORDER BY SESSION_DT
然而,我一直收到错误,
SQL Error: ORA-01489: result of string concatenation is too long
我非常确定输出可能会超过4000,因为这里提到的Web_link是url词干和url查询的连接值。
有没有办法绕过它,或者有其他选择?
13条答案
按热度按时间pgky5nke1#
您可以使用XMLAGG函数实现类似的功能:
这将返回一个LOB值,因此对行数没有限制。
lx0bsm1f2#
由于聚合字符串可以超过4000个字节,因此不能使用
LISTAGG
函数。您可能会创建一个返回CLOB
而不是VARCHAR2
的用户定义聚合函数。有一个用户定义的聚合示例,它在原始的askTom讨论中返回一个CLOB
,Tim从第一个讨论链接到该讨论。jaxagkaj3#
listagg
最近被ISO SQL标准(SQL:2016)涵盖。作为其中的一部分,它还获得了Oracle 12cR2支持的on overflow
子句。on overflow
子句支持truncate
选项(作为缺省on overflow error
行为的替代)。可选默认为三个句点(...)如果发生截断,将被添加为最后一个元素。
如果指定了WITH COUNT并发生截断,则省略的值数将放在括号中并附加到结果中。
有关
listagg
的on overflow
子句的更多信息:http://modern-sql.com/feature/listagghuus2vyu4#
12cR2中添加的新功能是
LISTAGG
的ON OVERFLOW
子句。包含此子句的查询将如下所示:以上命令将输出限制为4000个字符,但不会抛出
ORA-01489
错误。以下是
ON OVERFLOW
子句的一些附加选项:ON OVERFLOW TRUNCATE 'Contd..'
:在字符串末尾显示'Contd..'
(默认为...
)ON OVERFLOW TRUNCATE ''
:这将显示不带任何终止字符串的4000个字符。ON OVERFLOW TRUNCATE WITH COUNT
:这将在终止字符之后的末尾显示字符总数。例如:‘...(5512)
’ON OVERFLOW ERROR
:如果您预计LISTAGG
会失败并出现ORA-01489
错误(无论如何这都是默认错误)。LISTAGG Enhancements in 12c R2
dkqlctbz5#
您正在超过适用于
LISTAGG
的SQL限制4000字节。作为一种解决办法,您可以使用XMLAGG。
例如,
如果您希望拼接多列本身有4000字节,那么您可以拼接每列的XMLAGG输出,以避免SQL 4000字节的限制。
例如,
wz8daaqr6#
在公认的答案上再加上一句话。我遇到了类似的问题,最终使用了一个用户定义的函数,该函数返回lob而不是varchar2。以下是我的解决方案:
现在,与其做
我必须这么做
l7wslrjt7#
我可以容忍将我的字段连接成多行,每行少于4000个字符的限制--执行了以下操作:
nwsw7zdq8#
管理LISTAGG中的溢出
我们可以使用数据库12c SQL模式匹配函数Match_Recognition来返回不超过限制的值列表。
示例代码和更多解释在下面的链接中。
https://blogs.oracle.com/datawarehousing/entry/managing_overflows_in_listagg
x759pob29#
在某些场景中,意图是获取所有不同的LISTAGG密钥,而溢出是由于LISTAGG连接所有密钥而导致的。
这里有一个小例子
如果组很大,重复的键很快就会达到允许的最大长度,您就会得到
ORA-01489: result of string concatenation is too long
。遗憾的是,不支持
LISTAGG( DISTINCT y, '; ')
,但作为解决办法,可以使用LISTAGG忽略空值这一事实。使用ROW_NUMBER,我们将只考虑第一个键。当然,在子查询中使用
GROUP BY x,y
也可以得到相同的结果。ROW_NUMBER
的优点是可以使用所有其他聚合函数,如SUM(z)
所示。gdrx4gfi10#
谢谢你的建议。我在连接几个字段时也遇到了同样的问题,但即使是
xmlagg
也帮不了我-我仍然得到了ORA-01489。经过几次尝试,我找到了原因和解决方案:1.原因:我的
xmlagg
中有一个字段存储了大文本;1.解决方案:应用
to_clob()
函数。示例:
希望这对任何人都有帮助。
frebpwbc11#
我们在这里使用Oracle LISTAGG解决了类似的问题。我们分组的内容一度超过了4K的限制,但这个问题很容易解决,方法是让第一个数据集聚合前15个项目,每个项目都有256K的限制。
更多信息:我们有项目,这些项目有变更单,而变更单又有解释。为什么数据库设置为接受256K大小限制的更改文本块尚不清楚,但这是设计限制之一。因此,将变更解释反馈到表中的应用程序在254K停止并插入,然后获得下一组文本,如果>254K,则生成另一行,依此类推。因此,我们有一个项目到变更单,1:1。然后我们将这些作为1:N用于解释。LISTAGG将所有这些串联在一起。我们有RMRKS_SN值,每个备注和/或每254K字符1个。
发现最大的RMRKS_SN是31,所以我做了第一个数据集拉出SN 0到15,第二个数据集16到30,最后一个数据集31到45--嘿,让我们计划有人给一些变更单增加很多解释!
在SQL报告中,Tablix绑定到第一个数据集。要获取其他数据,表达式如下:
=First(字段!NON_STD_TXT.Value,“DataSet_EXPLAN”)&First(字段!NON_STD_TXT.Value,“DS_EXPLAN_SN_16_TO_30”)&First(Fields!Non_STD_TXT.Value,“DS_EXPLAN_SN_31_TO_45”)
对于我们来说,由于安全限制,我们必须让DB Group创建函数等。因此,只要有一点创造力,我们就不必进行用户聚合或UDF。
如果您的应用程序有某种类型的SN可供聚合,则此方法应该有效。我不知道等同的TSQL是什么--我们很幸运地为这份报告与Oracle打交道,LISTAGG对它来说是一个天赐之物。
代码是:
而在其他两个数据集中,只需为From中的子查询选择LISTAGG:
从..。
..。
..。诸若此类。
bfrts1fy12#
除了使用12c溢出之外,使用CLOB和substr也可以
Rtrim(DBMS_lob.substr(XMLAGG(XMLELEMENT(E,COLUMN_NAME,‘,’).EXTRACT(‘//Text()’)ORDER BY COLUMN_NAME).GetClobVal(),1000,1),‘,’)
hi3rlvi213#
要实现聚合并处理XML/HTML内容和Unicode字符,请使用以下工具:
如果您只需要处理XML/HTML,而不需要担心Unicode字符,您可以使用
这种方法的唯一缺点是,您只能选择已分组的列和要聚合的列。如果要将结果与其他列一起包含,则需要将其放置在公用表表达式(CTE)中,并将其与Group by列联接到同一个表。