嗨!
今天我学会了for xml path
技术来连接mssql中的字符串。由于我从未使用过mssql中的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个“名称”记录,但不会返回连接的所有“名称”记录。
[问题] :是否有可能像我想要的那样解决问题的第二种方式,如果有可能那么如何?
[免责声明] :问题对我来说并不是很严重(第一种方式只是有点丑陋但也很好),但是如何过来似乎很有意思:)
谢谢!
答案 0 :(得分: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, '');
答案 1 :(得分:1)
好的,所以我对Gordon Linoff建议的方式并不完全满意,因为我发现这个问题对我来说很实际,我在这里添加另一个解决方案而不使用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 */
显然,它的工作速度要慢得多,但如果行数不多,则不会对性能造成太大影响。在我的情况下,我有动态透视查询,这些字符串是为它构建的 - 我在枢轴中没有很多列,所以对我来说没问题。