2012-12-29 29 views
3

嗨! 今天我学到了for xml path技术来连接mssql中的字符串。由于我从来没有在mssql中使用过xml,谷歌也没有帮助,所以我需要问你。由xml路径串联字符串

让我们设想一下默认情况。我们需要从表中串连一些字符串:

declare @xmlRepNames xml = (
    select   
     ', [' + report_name + ']' 
    from (
     select distinct 
      report_order, 
      report_name 
     from #report 
    ) x 
    order by 
     report_order 
    for xml path(''), type) 

select 
    stuff((select @xmlRepNames.value('.', 'nvarchar(max)')), 1, 1, '') 

所以我得到水木清华这样的:

[str1], [str2], [strn] 

确定。它工作正常。但我有两个非常相似的连接块。所不同的只是在结果字符串的样子像:

  • [str1], [str2], [strn]
  • isnull([str1], 0) as [str1], isnull([str2], 0) as [str2], isnull([strn], 0) as [strn]

所以,我可以写2个非常相似的代码块(已经完成了,顺便说一句)与不同字符串构造函数或尝试扩展先前的代码以使xml变量包含2种构造函数,然后通过xml节点类型进行连接。做第二路上,我遇见了一些问题 - 我写这样的:

declare @xmlRepNames xml = (
    select 
     ', [' + report_name + ']' as name, 
     ', isnull([' + report_name + '], 0) as [' + report_name + ']' as res 
    from (
     select distinct 
      report_order, 
      report_name 
     from #report 
    ) x 
    order by 
     report_order 
    for xml path(''), type) 

select 
    stuff((select @xmlRepNames.value('/name', 'nvarchar(max)')), 1, 1, ''), 
    stuff((select @xmlRepNames.value('/res', 'nvarchar(max)')), 1, 1, '') 

但它引发错误"XQuery [value()]: 'value()' requires a singleton (or empty sequence), found operand of type 'xdt:untypedAtomic *'"
要替换(例如,'/name''/name[1]'或任何其他'/name[x]'),将只返回第x个'name'记录,但不是所有'name'记录连接。
[question]:是否有可能像我想要的第二种方式解决问题,如果有可能,那么该怎么做?
[免责声明]:现在的问题对我来说不是很严重(第一种方式只是有点丑,但也很好),但它似乎很有趣如何过来:) 谢谢!

+1

[与FOR XML的行连接,但具有多列?](http://stackoverflow.com/questions/7749041/row-concatenation-with-for-xml-but-with-multiple-columns) –

回答

2

您的子查询无法返回两个值。如果你只是想连接字符串,那么根本不需要数据类型xml。你可以做stuff()和子查询在一条语句:

declare @Rep1Names nvarchar(max) = (
    stuff((select ', [' + report_name + ']' as name 
      from (select distinct report_order, report_name 
       from #report 
       ) x 
      order by report_order 
      for xml path('') 
     ) 
     ), 1, 1, ''); 

declare @Rep2Names nvarchar(max) = (
    stuff(select ', isnull([' + report_name + '], 0) as [' + report_name + ']' as res 
      from (select distinct report_order, report_name 
       from #report 
       ) x 
      order by report_order 
      for xml path('') 
     ) 
    ), 1, 1, ''); 
0

好了,我还没有完全满意的方式戈登·利诺夫建议,因为我已经找到了这样的问题,实际我,我” M}这里添加另一种解决方案,而无需使用for xml path

declare 
    @pivot_sequence nvarchar(max), 
    @columns_sequence nvarchar(max) 

select 
    @pivot_sequence = coalesce(@pivot_sequence + ', [', '[') 
     + col_name + ']', 
    @columns_sequence = coalesce(@columns_sequence + ', ', '') 
     + 'isnull([' + col_name + '], 0) as [' + col_name + ']' 
from some_table 
order by 
    /* some_columns if needed to order concatenation */ 

显然,它会工作要慢得多,但在情况下,当你还没有多少行也不会显着业绩的影响。在我的情况下,我有动态透视查询,这些字符串是为它构建的 - 我不会在透视中有很多列,所以对我来说很好。