我有一个普通的SQL表,其中一列是XML,例如:
...
<Element><id>first</id></Element>
<Element><id>second</id></Element>
...
我需要用逗号分隔id列表:
id_list
---
first,second
目前,我已经实现了使用ids创建XMLTABLE:
id
----
first
second
然后使用Oracle的LISTAGG功能。 我想知道是否存在一些函数/循环(可能是FLWOR?)来获得相同的结果但不将XML输入转换为XMLTABLE。
非常感谢您的帮助
答案 0 :(得分:0)
如果必须,您可以执行我在下面的查询中显示的内容。
但是,我认为这不是一个好方法;你目前正在做什么,通过创建一个XML表,然后使用LISTAGG
,似乎更好。
with inputs ( xml_str ) as (
select '...
<Element><id>first</id></Element>
<Element><id>second</id></Element>
...'
from dual
)
-- End of test data (not part of the solution); SQL query begins below this line
select rtrim( regexp_replace( xml_str, '.*?(<Element><id>(.*?)</id></Element>|$)'
, '\2,', 1, 0, 'n')
, ',') as id_list
from inputs
;
ID_LIST
------------
first,second
答案 1 :(得分:0)
你可以在XMLDB函数中使用XPath string-join
function。
作为XMLQuery,如果您有一个值要处理(通过CTE和虚拟根节点提供示例数据):
with t (xml) as (
select xmltype('<root>
<Element><id>first</id></Element>
<Element><id>second</id></Element>
</root>') from dual
)
select xmlquery('
for $i in /root
return <e>{ fn:string-join($i/Element/id, ",") }</e>/text()'
passing xml
returning content
) as result
from t;
RESULT
--------------------------------------------------------------------------------
first,second
或使用XMLTable:
with t (xml) as (
select xmltype('<root>
<Element><id>first</id></Element>
<Element><id>second</id></Element>
</root>') from dual
)
select x.*
from t
cross join xmltable('
for $i in /root
return <e>{ fn:string-join($i/Element/id, ",") }</e>'
passing xml
columns result varchar2(4000) path '.'
) x;
RESULT
--------------------------------------------------------------------------------
first,second
我不确定在listagg()
上做这件事有多大优势,但将两者的性能与实际数据进行比较可能会很有意思,特别是如果有很多节点的话。除非通过将XMLTable列类型更改为CLOB,否则您可以使用listagg()
从该版本中获取更大的值。