2013-02-27 69 views
3

如何使用T-SQL在XML数据中查询多个节点,并将结果输出为单个逗号分隔的字符串?使用T-SQL查询XML字段

例如,我想获得的所有的目的地名称的列表在以下XML看起来像“德国,法国,英国,意大利,西班牙,葡萄牙”

<Holidays> 
     <Summer> 
     <Regions> 
     <Destinations> 
      <Destination Name="Germany" /> 
      <Destination Name="France" /> 
      <Destination Name="UK" /> 
      <Destination Name="Italy" /> 
      <Destination Name="Spain" /> 
      <Destination Name="Portugal" /> 
     </Destinations> 
     <Regions> 
     </Summer> 
    </Holidays> 

我试着是这样的:

Countries = [xmlstring].value('/Holidays/Summer/Regions/Destinations/@Name', 'varchar') 

回答

3

首先,从源XML表中获取的记录列表,你需要使用.nodes功能(DEMO):

select Destination.value('data(@Name)', 'varchar(50)') as name 
from [xmlstring].nodes('/Holidays/Summer/Regions/Destinations/Destination') 
    D(Destination) 

输出示例:

|  NAME | 
------------- 
| Germany | 
| France | 
|  UK | 
|  Italy | 
|  Spain | 
| Portugal | 

从这里,你要在目标值连接成一个逗号分隔的列表。不幸的是,这不是T-SQL直接支持的,所以你必须使用某种解决方法。如果您正在使用多行处理源表,最简单的方法就是FOR XML PATH('')技巧。在这个查询中,我使用了一个名为Data的源表,并将XML分成单独的记录,然后我用CROSS APPLYFOR XML PATH('')生成逗号分隔的行。最后,最终,从结果剥离创建列表(DEMO):

;with Destinations as (
    select id, name 
    from Data 
    cross apply (
     select Destination.value('data(@Name)', 'varchar(50)') as name 
     from [xmlstring].nodes('/Holidays/Summer/Regions/Destinations/Destination') D(Destination) 
    ) Destinations(Name) 
) 
select id, substring(NameList, 1, len(namelist) - 1) 
from Destinations as parent 
cross apply (
    select name + ',' 
    from Destinations as child 
    where parent.id = child.id 
    for xml path ('') 
) DestList(NameList) 
group by id, NameList 

样本输出(请注意,我添加了另一个XML片段的测试数据,以做出更加复杂的例子):

| ID |        COLUMN_1 | 
----------------------------------------------- 
| 1 | Germany,France,UK,Italy,Spain,Portugal | 
| 2 |     USA,Australia,Brazil | 
+1

谢谢您的回答细节和例子。我甚至不知道SQLFiddle存在。 – FloatLeft 2013-02-28 09:34:53