2017-03-31 36 views
0

我试图查询表中的XMLtype字段,该表中的元素名称在每次出现时都增加1。这些元素可能有1到很多级别,我想知道是否有一种方法来通配元素名称,以便它将基于名称搜索返回所有元素值,而不是将所有可能的名称级别联合起来?在找出这一步之后,我正在寻找listagg或连接结果。查询在Oracle中增加XML元素名称

select extractvalue(myXMLfield,'/doc/name1') from myTable 
union 
select extractvalue(myXMLfield,'/doc/name2') from myTable 
union 
select extractvalue(myXMLfield,'/doc/name3') from myTable 

VS某种的元素名称

select extractvalue(myXMLfield,'/doc/name%') from myTable 

XML样本通配符搜索的

<doc><name1>NAME_1</name1><name2>NAME_2</name2><name3>NAME_3</name3></doc> 

期望中的SQL查询VARCHAR串联输出

"NAME_1,NAME_2,NAME_3" 
+0

包括样品XML和期望的输出数据将是有益的。 –

+0

我添加了一些XML和SQL输出示例。 – Jared

回答

2

你可以使用XMLTable提取多个节点的值,并在XPath的子模式通配符节点名称(适当地设置列大小的实际数据):

select x.name 
from myTable t 
cross join XMLTable(
    '/doc/*[substring(name(), 1, 4) = "name"]' 
    passing myXMLfield 
    columns name varchar2(20) path '.' 
) x; 

NAME     
-------------------- 
NAME_1 
NAME_2 
NAME_3 

然后你可以只使用listagg()为最终输出:

select listagg(x.name, ',') within group (order by null) as names 
from myTable t 
cross join XMLTable(
    '/doc/*[substring(name(), 1, 4) = "name"]' 
    passing myXMLfield 
    columns name varchar2(20) path '.' 
) x; 

NAMES       
------------------------------ 
NAME_1,NAME_2,NAME_3 

以null排序不理想;如果您的真实数据具有其他属性或值,那么您可以提取并使用可能更好的排序。如果没有,你可以使用后“名”的部分,假设它确实总是数字,通过另一个子:

select listagg(x.name, ',') within group (order by x.id) as names 
from myTable t 
cross join XMLTable(
    '/doc/*[substring(name(), 1, 4) = "name"]' 
    passing myXMLfield 
    columns name varchar2(20) path '.', 
    id number path 'substring(name(.), 5)' 
) x; 
+0

这工作完美。查询性能也相当不错。谢谢。 – Jared