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)
如果仅包含字符"±",这将分别为您0xF1或0xB1columnName
如果您使用的字体不提供正确的字形,您仍然可能得到正确的结果而且字符错误.
请通过将查询转换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)
我们可能需要更多信息。以下是我在 SQL Server 2008 上重现的内容:
\n\nCREATE 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\nRun Code Online (Sandbox Code Playgroud)\n\n结果显示了原始特征。从 SQL Server 的角度来看,在查询中声明排序规则应该返回正确的字符,但表示层随后可能会转换为不同的字符,例如 UTF-8。
\n