You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 03:36:17