SQL Server 2017与UTF-8 XML:特殊字符处理差异原因咨询
SQL Server 2017 XML特殊字符处理差异解析
问题本质:字符编码与XML解析规则的双重作用
1. 表情符号(😎)数据丢失的原因
- 你使用
VARCHAR(MAX)存储XML字符串,而VARCHAR在SQL Server中是单字节编码类型(依赖数据库默认排序规则,通常为CP1252)。 - 表情符号😎属于Unicode补充平面字符(U+1F60E),需要4字节的UTF-8编码才能表示,但
VARCHAR无法容纳这类多字节的Unicode补充字符,在存储阶段就被转成了两个?符号。 - 当转换为
XML类型时,XML解析器看到的是已经被损坏的单字节?,这属于合法的XML字符,因此不会报错,最终输出保留了?。
2. ä/€触发错误的原因
- ä(U+00E4)和€(U+20AC)属于Unicode基本多语言平面(BMP),对应的UTF-8编码是2字节和3字节。
- 把这类UTF-8字符串存入
VARCHAR变量时,单字节编码无法正确识别多字节序列,导致字符串变成了不符合XML规范的非法字符序列。 - SQL Server的XML解析器会严格校验字符合法性,一旦发现非法序列,直接抛出
Msg 9420错误终止解析。
修复方案
- 改用
NVARCHAR(MAX)存储XML字符串,它支持完整的Unicode编码,能正确保存所有Unicode字符(包括表情符号):
DECLARE @DT NVARCHAR(MAX) = N'<?xml version="1.0"?> <Name>😎ä€</Name> ' DECLARE @XML XML SET @XML = @DT SELECT @XML -- 输出:<Name>😎ä€</Name>
- 若必须使用UTF-8编码,需确保字符串的实际编码与XML声明一致,可通过
VARBINARY类型传递UTF-8字节流再转换为XML:
DECLARE @DT VARBINARY(MAX) = 0xEFBBBF3C3F786D6C2076657273696F6E3D22312E302220656E636F64696E673D227574662D38223F3E0A3C4E616D653E0C2F4E616D653E0A DECLARE @XML XML SET @XML = @DT SELECT @XML
内容的提问来源于stack exchange,提问作者AcclaroDev
相关产品推荐
相关产品推荐

