2011-11-11 20 views
14

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

当我直接在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 

我在做什么错?

+1

欢迎StackOverflow上:如果您发布的代码,XML或数据样本,**请**在文本编辑器中突出显示这些行,然后单击编辑器工具栏上的“代码示例”按钮(“{}”),以良好地格式化和语法突出显示它! –

回答

1

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

CREATE DATABASE [Test] ON PRIMARY 
    ( 
    NAME = N'Test' 
    , FILENAME = N'...Test.mdf' 
    , SIZE = 3072KB 
    , FILEGROWTH = 1024KB 
    ) 
    LOG ON 
    ( 
    NAME = N'Test_log' 
    , FILENAME = N'...Test_log.ldf' 
    , SIZE = 1024KB 
    , FILEGROWTH = 10% 
    ) 
    COLLATE SQL_Latin1_General_CP850_BIN2 
GO 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
SET ANSI_PADDING ON 
GO 
CREATE TABLE [dbo].[MyTable] 
    (
    [SomeCol] [varchar](50) NULL 
    ) ON [PRIMARY] 
GO 
Insert MyTable(SomeCol) 
Select '±' Collate SQL_Latin1_General_CP1_CI_AS 
GO 
Select SomeCol, SomeCol Collate SQL_Latin1_General_CP1_CI_AS 
From MyTable 

结果显示原始字符。在查询中声明排序规则应该从SQL Server的角度返回适当的字符,但可能会出现这种情况,即表示层然后转换为类似UTF-8的东西。

8

完成字符集转换隐式地在数据库连接级别上执行。您可以使用参数“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 

这将让你0xF10xB1分别若columnName只包含字符“±”

你仍然可能得到正确的结果,但错误的字符,如果你使用的是不提供公关字体操作符号。

请仔细铸造查询检查你的角色的实际内部表示VARBINARY在一个适当的样品并验证该代码是否确实对应于定义的数据库排序规则应用的整理和数据库SQL_Latin1_General_CP850_BIN2

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

差异只要转换总是按照相同的方式进行,整理可能会被忽视。添加具有不同排序规则的客户端时,会出现问题。然后您可能会发现内部转换无法正确匹配字符。所有这些,你应该记住,在解释结果集时,Management Studio通常并不是最终的参考。即使它在MS中看起来很乱,它仍然可能是正确的输出。问题是这些记录是否在您的应用程序中正确显示。

1

尝试:

SELECT CAST(CAST([field] AS VARBINARY) AS varchar) 
+0

这对我有用。我还需要补充一点,程序员应该像(VARBINARY(120))... VARCHAR(120)那样指示长度。否则会削减输出。 –

相关问题