sql-server - SQL Server - 将 varchar 转换为另一种排序规则(代码页)以修复字符编码

标签 sql-server character-encoding collation

我正在查询使用 SQL_Latin1_General_CP850_BIN2 排序规则的 SQL Server 数据库。表行之一具有 varchar,其值包含 +/- 字符(Windows-1252 代码页中的十进制代码 177)。

当我直接在 SQL Server Management Studio 中查询表时,我在该行中得到一个乱码字符而不是 +/- 字符。当我使用此表作为 SSIS 包中的源时,目标表(使用典型的 SQL_Latin1_General_CP1_CI_AS 排序规则)以正确的 +/- 字符结束。

我现在必须构建一种无需 SSIS 即可直接查询源表的机制。我该如何做到这一点才能获得正确的字符而不是乱码?我的猜测是,我需要将该列转换/转换为 SQL_Latin1_General_CP1_CI_AS 排序规则,但这不起作用,因为我不断收到乱码字符。

我尝试了以下方法,但没有成功:

select 
columnName collate SQL_Latin1_General_CP1_CI_AS
from tableName

select 
cast (columnName as varchar(100)) collate SQL_Latin1_General_CP1_CI_AS
from tableName

select 
convert (varchar, columnName) collate SQL_Latin1_General_CP1_CI_AS
from tableName

我做错了什么?

最佳答案

字符集转换是在数据库连接级别隐式完成的。您可以使用参数“Auto Translate=False”在 ODBC 或 ADODB 连接字符串中强制关闭自动转换。不建议这样做。 请参阅:https://msdn.microsoft.com/en-us/library/ms130822.aspx

当数据库和客户端代码页不匹配时,SQL Server 2005 中会出现代码页不兼容的情况。 https://support.microsoft.com/kb/KbView/904803

SQL 管理控制台 2008 及更高版本是 UNICODE 应用程序。所有输入或请求的值都会在应用程序级别进行解释。与列排序规则之间的对话是隐式完成的。您可以通过以下方式验证这一点:

SELECT CAST(N'±' as varbinary(10)) AS Result

这将返回 0xB100,它是 Unicode 字符 U+00B1(如在管理控制台窗口中输入的那样)。您无法关闭 Management Studio 的“自动翻译”。

如果您在选择中指定了不同的排序规则,只要“自动翻译”仍然处于事件状态,您最终会遇到双重转换(可能会丢失数据)。在选择过程中,原始字符首先转换为新的排序规则,这反过来又将“自动翻译”为“正确的”应用程序代码页。这就是为什么您的各种 COLLATION 测试仍然显示相同的结果。

如果将结果转换为 VARBINARY 而不是 VARCHAR,则可以验证指定排序规则是否对选择产生影响,这样 SQL Server 转换就不会失效在呈现之前由客户:

SELECT cast(columnName COLLATE SQL_Latin1_General_CP850_BIN2 as varbinary(10)) from tableName
SELECT cast(columnName COLLATE SQL_Latin1_General_CP1_CI_AS as varbinary(10)) from tableName

如果 columnName 仅包含字符“±”,这将分别为您提供 0xF10xB1

如果您使用的字体没有提供正确的字形,您仍然可能会得到正确的结果,但会得到错误的字符。

请通过在适当的示例上将查询强制转换为 VARBINARY 来仔细检查字符的实际内部表示形式,并验证此代码是否确实对应于定义的数据库排序规则 SQL_Latin1_General_CP850_BIN2

SELECT CAST(columnName as varbinary(10)) from tableName

只要始终以相同的方式进出转换,应用程序排序规则和数据库排序规则中的差异可能会被忽视。一旦添加具有不同排序规则的客户端,就会出现问题。然后你可能会发现内部转换无法正确匹配字符。

尽管如此,您应该记住,在解释结果集时,Management Studio 通常不是最终引用。即使它在 MS 中看起来很乱,它仍然可能是正确的输出。问题是记录是否正确显示在您的应用程序中。

关于sql-server - SQL Server - 将 varchar 转换为另一种排序规则(代码页)以修复字符编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8089907/

相关文章:

java - 包含非 UTF-8 字符的源的 Http GET

database - 为什么需要区分大小写的数据库?

javascript - 准备数组以便在闭包中进行排序

javascript - 有效地替换字符串中的所有重音字符?

sql - 在sql server management studio 2014中重命名数据库名称

sql - 将连接表的列旋转为行

php - 在mysql中使用UTF-8的终极方法

sql - 查找组之间的共同数据

sql-server - SSIS:将数据从excel导入sql server数据库,文件最后修改日期条件

csv - 如何读取非UTF8编码的csv文件?