SQL Server XQuery用AS [data()]查询时如何去除默认空格分隔符
问题背景
参考调整了shnugo针对「Select all XML nodes from XML column」问题的解答方案后,代码运行基本符合预期,但生成的列表项之间会自动插入空格。
核心需求:
- 阻止FOR XML输出默认的空格分隔符,或直接指定逗号作为分隔符
- 现有测试代码输出为
IsColA, IsColB, IsColC, IsColD,,期望输出为IsColA,IsColB,IsColC,IsColD, - 已知可通过
Replace(indlist, ' ', '')去除空格,但希望直接在XQuery内部完成配置,不额外使用替换函数 - 数据库兼容级别为100(SQL Server 2008),无法使用FOR JSON语法
测试代码
declare @table TABLE(ID int, IsColA bit, IsColB bit, IsColC bit, IsColD bit, IsColE bit) insert @table select 1, 1, 1, 1, 1, 0 SELECT * FROM ( SELECT TagName +',' AS [data()] FROM ( SELECT ID AS ID , Nodes.value('local-name(.)','varchar(32)') AS TagName , Nodes.value('text()[1]','bit') AS TagValue FROM ( SELECT ID, CONVERT(XML, (SELECT pbInner.* FOR XML PATH('row'))) as Rows FROM @table pbInner WHERE pbInner.ID = 1 ) t CROSS APPLY t.Rows.nodes('/row/*') A(Nodes) ) cols WHERE cols.TagName LIKE 'is%' and cols.TagName NOT IN ('IsToBeExcluded', 'IsAlsoToBeExcluded') AND TagValue = 1 FOR XML PATH('') ) inds(indlist)
解决方案
FOR XML PATH 搭配 [data()] 列别名时,自动在相邻值之间插入单个空格是SQL Server的固定默认行为,没有对应的开关参数可以直接关闭。不需要在外层套REPLACE,两种兼容SQL Server 2008的原生实现方式都可以直接输出无空格结果:
方案1:调整FOR XML取值逻辑,规避自动空格规则
放弃[data()]的自动拼接模式,将拼接结果转为XML类型后用XQuery提取纯文本,全程不会触发自动加空格逻辑,同时能自动处理特殊字符转义,稳定性更高:
SELECT indlist = ( SELECT TagName + ',' FROM ( SELECT Nodes.value('local-name(.)','varchar(32)') AS TagName, Nodes.value('text()[1]','bit') AS TagValue FROM ( SELECT CONVERT(XML, (SELECT pbInner.* FOR XML PATH('row'))) as Rows FROM @table pbInner WHERE pbInner.ID = 1 ) t CROSS APPLY t.Rows.nodes('/row/*') A(Nodes) ) cols WHERE cols.TagName LIKE 'is%' AND cols.TagName NOT IN ('IsToBeExcluded', 'IsAlsoToBeExcluded') AND TagValue = 1 FOR XML PATH(''), TYPE ).value('.', 'varchar(max)')
方案2:直接在XQuery内完成过滤和拼接
用XQuery原生的string-join函数直接指定逗号作为分隔符,把节点过滤、取值、拼接逻辑全部整合在XML解析阶段,代码更简洁,性能也更好:
SELECT indlist = Rows.value('string-join(for $n in /row/*[starts-with(local-name(.), "Is") and not(local-name(.) = ("IsToBeExcluded","IsAlsoToBeExcluded")) and text()[1] = 1]/local-name(.), ",") + ","', 'varchar(max)') FROM ( SELECT CONVERT(XML, (SELECT pbInner.* FOR XML PATH('row'))) as Rows FROM @table pbInner WHERE pbInner.ID = 1 ) t
两种方案最终输出均为期望的IsColA,IsColB,IsColC,IsColD,,不需要额外做字符串替换,完全兼容SQL Server 2008版本。
内容的提问来源于stack exchange,提问作者lukep
相关产品推荐
相关产品推荐

