小编典典

xml路径的字符串串联

sql

你好!今天,我学习了for xml path在mssql中连接字符串的技术。由于我从未在mssql中使用过xml,而google却没有帮助,所以我需要问你。

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

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个非常相似的代码块(已经完成,btw),或尝试将先前的代码扩展为具有包含2种构造函数的xml变量,然后按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'为to'/name[1]'或任何其他替换,'/name[x]'将仅返回第x个“名称”记录,而不是所有串联的“名称”记录。
[问题] :是否可以像我想要的那样解决问题的第二种方式,如果可能的话该如何解决?
[免责声明] :这个问题现在对我来说并不十分严重(第一种方法有点难看,但还可以),但是如何克服似乎很有趣:)谢谢!


阅读 262

收藏
2021-04-07

共1个答案

小编典典

您的子查询不能返回两个值。如果只想连接字符串,则根本不需要xml数据类型。您可以stuff()在单个语句中执行and子查询:

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, '');
2021-04-07