当我跑步时:
SELECT name + '&'
FROM sys.databases
FOR XML PATH('');
代码返回以下内容:
master&tempdb&model&msdb&
我真正想要的是:
master&tempdb&model&msdb&
我也尝试过:
SELECT name + CHAR(38)
FROM sys.databases
FOR XML PATH('');
这也不起作用。首先如何获得预期的结果?
没有类似的内容
REPLACE(CAST('master&...l&msdb&' AS NVARCHAR(MAX)), '&', '&')
答案 0 :(得分:2)
FOR XML
子句默认情况下返回文本,因此结果字符串包括XML预定义的实体引用,例如用于表示与符号的&
,以表示XML中的特殊字符。
为避免在结果中引用实体,请在TYPE
子句中包含FOR XML
,以强类型XML而不是文本的形式返回值,从而可以在上调用value
方法XML节点以获取值为nvarchar(MAX)
的值,而没有实体引用:
SELECT (
SELECT name + '&'
FROM sys.databases
FOR XML PATH(''), TYPE
).value('(./text())[1]', 'nvarchar(MAX)');
上面的示例包含跟您的原始查询类似的结尾的&符号。避免不必要的定界符的一种方法是使用STUFF
。下面是另一个示例,该示例将分隔符添加到每个值之前,并删除不需要的第一个。同样,单例节点值(./text())[1]
的指定将提高性能,这是一个考虑因素
用于更大的查询。
SELECT STUFF((
SELECT '&' + name
FROM sys.databases
FOR XML PATH(''), TYPE
).value('(./text())[1]', 'nvarchar(MAX)'), 1, 1, '');
我要补充一点,您可以使用更简洁,更不复杂的STRING_AGG
技术来避免SQL Server 2017+和Azure SQL数据库中聚合字符串连接的XML丑陋:
SELECT STRING_AGG(name, '&')
FROM sys.databases;
有关使用FOR XML
进行字符串聚合的详细说明,请参见this answer。