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

lun*_*ign 20 sql-server collation character-encoding

我正在查询使用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
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

小智 13

字符集转换在数据库连接级别上隐式完成.您可以使用参数"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-Management Console 2008及更高版本是UNICODE应用程序.输入或请求的所有值在应用程序级别上都被解释为.与列整理的对话是隐式完成的.您可以通过以下方式验证:

SELECT CAST(N'±' as varbinary(10)) AS Result
Run Code Online (Sandbox Code Playgroud)

这将返回0xB100Unicode字符U + 00B1(在管理控制台窗口中输入).您无法为Management Studio关闭"自动翻译".

如果在选择中指定了不同的排序规则,只要"自动翻译"仍处于活动状态,您最终将进行双重转换(可能会丢失数据).在选择期间首先将原始字符转换为新的排序规则,然后将"自动转换"转换为"正确的"应用程序代码页.这就是为什么你的各种COLLATION测试仍然显示所有相同的结果.

您可以验证指定排序规则DOES是否在select中有效,如果您将结果转换为,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
Run Code Online (Sandbox Code Playgroud)

如果仅包含字符"±",这将分别为您0xF10xB1columnName

如果您使用的字体不提供正确的字形,您仍然可能得到正确的结果而且字符错误.

请通过将查询转换VARBINARY为正确的示例来仔细检查角色的实际内部表示,并验证此代码是否确实对应于已定义的数据库归类SQL_Latin1_General_CP850_BIN2

SELECT CAST(columnName as varbinary(10)) from tableName
Run Code Online (Sandbox Code Playgroud)

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

总而言之,您应该记住,在解释结果集时,Management Studio通常不是最终参考.即使它在MS中看起来很乱,它仍然可能是正确的输出.问题是记录是否在您的应用程序中正确显示.


小智 5

必须使用转换,而不是强制转换:

SELECT
 CONVERT(varchar(50), N'æøåáä??ç?é???ö??ý?žš')
 COLLATE Cyrillic_General_CI_AI
Run Code Online (Sandbox Code Playgroud)

http://blog.sqlpositive.com/2010/03/using-convert-with-collat​​e-to-strip-accents-from-unicode-strings/


Tho*_*mas 1

我们可能需要更多信息。以下是我在 SQL Server 2008 上重现的内容:

\n\n
CREATE DATABASE [Test] ON  PRIMARY \n    ( \n    NAME = N'Test'\n    , FILENAME = N'...Test.mdf' \n    , SIZE = 3072KB \n    , FILEGROWTH = 1024KB \n    )\n    LOG ON \n    ( \n    NAME = N'Test_log'\n    , FILENAME = N'...Test_log.ldf' \n    , SIZE = 1024KB \n    , FILEGROWTH = 10%\n    )\n    COLLATE SQL_Latin1_General_CP850_BIN2\nGO\nSET ANSI_NULLS ON\nGO\nSET QUOTED_IDENTIFIER ON\nGO\nSET ANSI_PADDING ON\nGO\nCREATE TABLE [dbo].[MyTable]\n    (\n    [SomeCol] [varchar](50) NULL\n    ) ON [PRIMARY]\nGO\nInsert MyTable( SomeCol )\nSelect '\xc2\xb1' Collate SQL_Latin1_General_CP1_CI_AS\nGO\nSelect SomeCol, SomeCol Collate SQL_Latin1_General_CP1_CI_AS\nFrom MyTable\n
Run Code Online (Sandbox Code Playgroud)\n\n

结果显示了原始特征。从 SQL Server 的角度来看,在查询中声明排序规则应该返回正确的字符,但表示层随后可能会转换为不同的字符,例如 UTF-8。

\n