PRB: SQL Server ODBC 驱动程序将语言事件转换为 Unicode

文章翻译 文章翻译
文章编号: 234748 - 查看本文应用于的产品
本文的发布号曾为 CHS234748
展开全部 | 关闭全部

症状

使用 MDAC 2.1 或更高版本的 SQL Server ODBC 驱动程序(版本 3.70.0623 或更高版本)或 OLEDB 提供程序(版本 7.01.0623 或更高版本)时,即使已禁用连接的“自动转换”功能,有时可能会遇到将字符数据从客户端代码页转换为服务器代码页的情况。

原因

“自动转换”是唯一可引起代码页转换的机制。 SQL Server 7.0 ODBC 驱动程序和 OLEDB 提供程序在连接到 MSDE 1.0、SQL Server 7.0 或相应的更高版本时引入了新的功能。 所有作为语言事件发送的 SQL 语句在发送到服务器前,均在客户端上转换为 Unicode。 这样做的结果类似于,通过语言事件对从客户端到服务器的所有数据进行“自动转换”,不考虑连接的当前“自动转换”设置。 这一般不会导致任何问题,但尝试存储来自非 SQL Server 代码页的未转换字符数据则是个例外。

替代方法

请不要在代码页 Y SQL Server 中存储代码页 X 的数据(例如,在代码页 1252 服务器中存储代码页 950 的数据)。 尽管早期版本 SQL Server 中有时也可能出现上述情况,但始终没有支持过它。 对于 1252 SQL Server 而言,除了 1252 的字符外,其它字符均不是有效字符数据。 来自不同代码页的非 Unicode 字符数据将不能正确地排序,而且对于双字节 (DBCS) 数据而言,SQL Server 将不能正确识别字符边界。 这样会导致严重的问题,如下列 Microsoft Knowledge Base 文章所述:
155723 INF: SQL Server 对 DBCS 字符串的截断
对于 SQL Server 代码页来说,最佳选择是使用访问该服务器的客户端的代码页。

服务器和客户端可能有不同的代码页,但必须确保启用客户端上的“自动转换”,以便在各种情况下对发送到(或来自)服务器代码页的数据进行正确的转换。

如果服务器必须存储来自多个代码页的数据,则可以将数据存储到 Unicode 列 (NCHAR/NVARCHAR/NTEXT) 中。

如果环境要求将代码页 X 的数据存储到代码页 Y SQL Server 上,则仅有的两种可靠方式是:
  • 将数据存储在二进制列 (BINARY/VARBINARY/IMAGE) 中。
    -或者-
  • 编写自己的应用程序,以使用“远程过程调用”(RPC),使所有的 SQL 语句都处理字符数据。 通过 RPC 事件发送的数据不进行此类转换。 请注意,在驱动程序或 DSN 级别上将无法更改所发送的事件的类型。 某个命令究竟是作为语言事件发送还是作为 RPC 事件发送,完全取决于编程人员编写应用程序时所选的 API 和语法。

更多信息

在把来自客户端代码页的字符数据发送给服务器之前,“自动转换”(即更新 ODBC 应用程序中的“对字符数据执行转换”复选框)将该字符数据转换为服务器代码页,其中使用 Unicode 作为转换媒介。 但是,在将作为语言事件发送的 SQL 语句放到线上前,3.7 版的 SQL Server ODBC 驱动程序也把所有这些 SQL 语句转换为 Unicode,其作用类似于“自动转换”,但不受“自动转换”设置的限制。 相比而言,从服务器流回客户端的字符数据将考虑“自动转换”标志。如果已关闭“自动转换”,数据就会到达客户端应用程序,其字符代码与服务器上数据的字符代码相同。 与此类似,通过关闭“自动转换”可以禁用客户端到服务器 RPC 事件的数据转换。 以下是演示这种情况如何影响语言事件的一个简单脚本。 该示例在代码页 1252 客户端(连接代码页 437 服务器)的查询分析器上运行:

    -- 此处关闭自动转换。
    USE tempdb
    GO
    CREATE TABLE t1 (c1 int, c2 char(1))
    GO
    
    -- 输入人民币字符,使用按键 ALT-0165。
    INSERT INTO t1 VALUES (1, '?') 
    SELECT c1, c2, ASCII (c2) FROM t1
  •         c1          c2               
            ----------- ---- ----------- 
            1           ?    157
            
            (1 row(s) affected)
    

请注意上例中的下列内容:

  • 尽管在这个批处理过程中关闭了“自动转换”,但字符代码 165( 代码页 1252 中的日元)还是被转换为 157(代码页 437 中的日元)。 这是因为 ODBC 驱动程序在把 SQL 字符串发送给服务器之前,把它转换为 Unicode,所以服务器能把该字符串转换为代码页 437 所储存的相应字符。
  • 当客户端运行 SELECT 来检索刚存储的数据时,字符 157 以未转换的形式到达客户端(157 在代码页 1252 客户端上显示为框“?”)。 这是因为本文所述的转换仅适用于从客户端发送给服务器的数据,而不适用于从服务器发送给客户端的数据。 由于已将“自动转换”设置为关,因此数据将不进行转换。

    -- 在运行下列批处理文件之前,重新开启自动转换。
    INSERT INTO t1 VALUES (2, '¥') 
    SELECT c1, c2, ASCII (c2) FROM t1
        c1          c2               
        ----------- ---- ----------- 
        1           ?    157
        2           ?    157
        
        (2 row(s) affected)
这种情况下,尽管重新打开“自动转换”不会对客户端到服务器的转换有任何影响(即正确地将字符代码 165 转换为字符代码 157),但对从服务器检索的数据却会有影响。 请注意,如果此时运行 SELECT 语句(打开“自动转换”),则日元符号将正确地显示在代码页 1252 应用程序中,这是因为“自动转换”机制已将其从字符代码 157 转换回字符代码 165。

使用 SQL Server ODBC 驱动程序 3.70 版或更高版本并连接 SQL Server 7.0 或更高版本时,将会看到上述情况(在客户端上将语言事件转换为 Unicode)。 使用旧的 ODBC 驱动程序或使用 3.7 版驱动程序来连接 SQL Server 6.5 或更早版本时,并不会出现上述情况。 此外,如果是将数据存储到 Unicode 列 (NCHAR/NVARCHAR/NTEXT) 中,则转换将不会出现问题。

属性

文章编号: 234748 - 最后修改: 2003年10月7日 - 修订: 1.2
这篇文章中的信息适用于:
  • Microsoft SQL Server 7.0 标准版
  • Microsoft Open Database Connectivity 3.7
  • Microsoft Data Engine 1.0
  • Microsoft SQL Server 2000 标准版
关键字:?
kbprb KB234748
Microsoft和/或其各供应商对于为任何目的而在本服务器上发布的文件及有关图形所含信息的适用性,不作任何声明。 所有该等文件及有关图形均"依样"提供,而不带任何性质的保证。Microsoft和/或其各供应商特此声明,对所有与该等信息有关的保证和条件不负任何责任,该等保证和条件包括关于适销性、符合特定用途、所有权和非侵权的所有默示保证和条件。在任何情况下,在由于使用或运行本服务器上的信息所引起的或与该等使用或运行有关的诉讼中,Microsoft和/或其各供应商就因丧失使用、数据或利润所导致的任何特别的、间接的、衍生性的损害或任何因使用而丧失所导致的之损害、数据或利润不负任何责任。

提供反馈

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com