由逗号

时间:2017-04-30 11:04:00

标签: xml oracle xmltable

我有一个普通的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。

非常感谢您的帮助

2 个答案:

答案 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()从该版本中获取更大的值。