通过


当客户端计算机的代码页与数据库的代码页不同时,字符数据表示不正确

原始产品版本:SQL Server
原始 KB 数: 904803

现象

假设出现了下面这种情景:

  • 使用 SQL Server Management Studio 从使用非 Unicode 数据类型的 SQL Server 数据库中查询字符数据。 例如,SQL Server 数据库使用charvarchartext数据类型。

  • 客户端计算机的代码页不同于数据库的代码页。 代码页与数据库的排序规则相关联。

在此方案中,字符数据被错误地表示。

例如,可能会遇到以下问题之一:

  • 字符数据表示为问号(?)。 如果在查询字符数据之前将字符数据插入或更新为非 Unicode 数据类型,则可能会看到此问题。 如果在具有不同代码页的客户端计算机上使用 SQL Server Management Studio 进行此更改,则会出现此问题。

  • 字符数据表示为损坏的数据。 代码页 X 的字符数据存储在代码页 Y 的非 Unicode 列中。此外,不会转换字符数据。 使用 SQL Server Management Studio 查询字符数据时,会出现此问题。

    注意

    使用 SQL Server Management Studio 查询字符数据时,如果禁用字符数据设置(也称为Auto Translate参数)的“执行转换”,则正确表示字符数据。 该 Auto Translate 参数是 Microsoft OLE DB Provider for SQL Server 和用于 OLE DB 的 Microsoft .NET Framework 数据提供程序的属性的参数 ConnectionString

原因

出现此问题的原因是代码页 X 的字符数据存储在代码页 Y 的非 Unicode 列中,不受支持。

在 SQL Server 中,使用非 Unicode 数据类型的字符串文本时,将使用从数据库排序规则派生的数据库的默认代码页转换字符串文本。 将代码页 X 的字符数据存储在代码页 Y 列中可能会导致数据丢失或数据损坏。

如果字符数据表示为损坏的数据,则仅当禁用 Auto Translate Microsoft OLE DB Provider for SQL Server 的参数或 Microsoft .NET Framework Data Provider for OLE DB 时,才能正确表示数据。

注意

SQL Server Management Studio 使用 Microsoft .NET Framework Data Provider for SQL Server 连接到 SQL Server 数据库。 此数据提供程序不支持参数 Auto Translate

解决方法

若要解决此问题,请使用以下方法之一:

方法 1:使用 Unicode 数据类型而不是非 Unicode 数据类型

将列更改为 Unicode 数据类型,以避免代码页转换导致的所有问题。 例如,使用ncharnvarcharntext数据类型。

方法 2:对数据库使用适当的排序规则

如果必须使用非 Unicode 数据类型,请始终确保数据库的代码页和任何非 Unicode 列的代码页可以正确存储非 Unicode 数据。 例如,如果要存储代码页 949(朝鲜文)字符数据,请对数据库使用朝鲜语排序规则。 例如,对 Korean_Wansung_CI_AS 数据库使用排序规则。

方法 3:使用“binary”或“varbinary”数据类型

如果希望数据库直接存储和检索未尝试执行适当的代码页转换的字符的确切字节值,请使用 binaryvarbinary 数据类型。

方法 4:使用不同的工具来存储和检索数据并禁用“自动翻译”参数

警告

我们不测试或支持将代码页 X 的字符数据存储在代码页 Y 列中。此操作可能会导致语言上不正确的查询结果、不正确的字符串匹配或排序以及意外的代码页转换(数据损坏)。 我们鼓励你使用其他方法之一来解决此问题。

使用 Microsoft OLE DB Provider for SQL Server 连接到具有不同代码页的数据库,并尝试从非 Unicode 数据类型列查询字符数据时,请确保将未传输的字符存储在数据库中。

注意

下面的示例假定客户端计算机的代码页是朝鲜语(CP949),SQL Server 数据库的代码页是英语(CP1252)。 必须将代码示例中的占位符替换为适合你的情况的值。

若要解决此问题,请按照以下步骤操作:

  1. 手动将字符转换为原始数据,然后使用数据库的代码页将数据插入数据库。 若要执行此操作,请使用类似于以下代码片段的代码片段:

    string strsrc="가";string strsrc="가";
    string strtag=Encoding.GetEncoding(1252).GetString(Encoding.GetEncoding(949).GetBytes (strsrc));
    sql="insert into <tablename> (<column>,) values ('" + strtag + "')";
    // code for updating the database;
    
  2. 若要查询数据,请使用 Microsoft OLE DB Provider for SQL Server 或 Microsoft .NET Framework Data Provider for SQL Server 连接到数据库,然后将参数设置为 Auto Translate False< a0/>。 若要执行此操作,请使用类似于以下代码片段的代码片段:

    OleDbConnection conn=new OleDbConnection("Provider=SQLOLEDB;" +
    " Initial Catalog =<yourdatabase>;"+
    "User id=<youruserid>; Password=<yourpassword>;"+
    "Auto Translate=False");
    // code for representing the character data;
    

详细信息

若要重现该问题,请执行以下步骤:

  1. 在将朝鲜语(CP949)作为默认代码页的客户端计算机上,启动 SQL Server Management Studio。

  2. 连接到具有英语(CP1252)作为默认代码页的数据库。

  3. 使用以下查询在数据库中创建表:

    CREATE TABLE tbTest (A char(20), NA nchar(10), Comment char(20))
    
  4. 使用以下查询将朝鲜文字符插入数据库中:

    INSERT INTO tbTest (A,NA,Comment) VALUES('가',N'가','SQLServer/INSERT')
    
  5. 使用以下查询创建一个选择查询以检索数据:

    SELECT * FROM tbTest
    

你会收到以下结果。 A 列中的值是问号。


A                    NA         Comment
-------------------- ---------- --------------------
?                    가          SQLServer/INSERT

参考