【发布时间】:2017-07-03 18:35:48
【问题描述】:
一段 tsql 代码从生产环境到测试环境的行为并不相同。当下面的代码在 prod 上执行时,它会带回数据
SELECT [col1xml]
FROM [DBName].[dbo].[Table1] (NOLOCK)
WHERE (cast([col1xml] as xml).value('(/Payment/****/trn1)[1]','nvarchar(20)') ='123456'))
但是,相同的代码在测试中运行时会返回以下错误。
消息 9402,第 16 级,状态 1,第 9 行 XML解析:第1行,第38个字符,无法切换编码
我已经看到了这个 UTF 转换站点提供的修复程序,这在 prod 和 test 中都有效。见下文。但是,我需要向开发人员提供一个答案,说明为什么会发生这种行为以及他们应该更改代码的理由(如果是这样的话)
WHERE CAST(
REPLACE(CAST(col1xml AS VARCHAR(MAX)), 'encoding="utf-16"', 'encoding="utf-8"')
AS XML).value('(/Payment/****/trn1)[1]','NVARCHAR(max)') ='123456')
我已经比较了两个数据库,并寻找了任何明显的东西,例如 ansi null 和 ansi 填充。一切都和 SQL Server 的版本一样。这是 SQL SERVER 2012 11.0.5388 版本。环境之间的数据不同,但表架构相同,col1xml的数据类型为ntext。
【问题讨论】:
-
因为 XML 的编码(隐式或显式)完全由底层字符串类型确定,所以您的 XML 文档应该不包含编码指令——这些指令除了采取占用空间并可能使解析器绊倒。如果无法避免获取它们,最好在存储它们时完全剥离它们(也就是说,不要用
encoding="utf-8"替换它们,用nothing 替换它们)。可以说服大多数 XML 库不输出 XML 声明,或者至少不输出带有编码的声明。
标签: sql-server xml tsql casting character-encoding