【问题标题】:Unicode conversion, database woes (Delphi 2007 to XE2)Unicode 转换,数据库问题(Delphi 2007 到 XE2)
【发布时间】:2012-05-20 01:27:16
【问题描述】:

目前,我正在将我们所有的 Delphi 2007 代码库更新到 Delphi XE2。最大的考虑是 ANSI 到 Unicode 的转换,我们通过将所有基本类型(char/string)重新定义为 ANSI 类型(ansichar/ansistring)来处理这个问题。在我开始使用数据库之前,这在我们的许多程序中都有效。

当我将从文件读取的信息存储到 SQL Server 2008 数据库中的程序转换时,问题就开始了。使用字符串定位数据的简单查询突然会失败,例如:

SELECT id FROM table WHERE name = 'something'

name 字段是varchar。我发现我可以通过在字符串名称前加上N 来成功完成查询。我的印象是varchar 只能 存储 ANSI 字符,但它似乎在存储 Unicode?​​p>

更多信息:Delphi 中的名称字段是string[13],但我尝试删除[13]。数据库排序规则为SQL_Latin1_General_CP1_CI_AS。我们使用 ADO 与数据库交互。连接信息存储在 ODBC 管理器中。

注意:由于 Panagiotis 的一些指导,我已经解决了我的实际问题。我们从地图文件中读取的名称是array[1..24] of AnsiChar。该值被隐式转换为string[13],其中包括空字符。所以一个 5 个字符的名字实际上是作为 5 个字符 + 8 个空字符存储在数据库中的。

【问题讨论】:

    标签: sql-server sql-server-2008 delphi unicode ansi


    【解决方案1】:

    varchar 字段不存储 Unicode 字符。它们将 ASCII 值存储在由字段排序规则指定的代码页中。当您尝试存储 Unicode 或来自不同代码页的数据时,SQL Server 将 try to convert characters 到正确的代码页。您可以禁用此功能,但最好的选择是通过在您的应用程序中使用 nvarchar 字段和 UnicodeString 来避免整个混乱。

    您提到您将应用程序中的所有字符类型更改为 ANSI,而不是 UNICODE 类型。如果你想使用 UNICODE,你应该使用像 UnicodeString 这样的 UNICODE 类型。否则,您的值将在发送到您的服务器时转换为 ANSI。当您创建发送到服务器的 AnsiString 时,此转换由您的代码完成。

    顺便说一句,您的选择语句在字段中存储了一个 ASCII 值。如果要将其存储为 unicode 值,则必须在该值前面加上 N,例如 g

    SELECT id FROM table WHERE name = N'something'
    

    即使这样也不能保证您的数据将以 Unicode 格式到达服务器。如果将语句存储在 AnsiString 中,则整个语句在发送到服务器之前将转换为 ANSI。如果您的应用进行了错误的转换,您最终会在服务器上得到损坏的数据。

    解决方法很简单,只需使用参数化语句将 unicode 值作为 unicode 参数传递并存储在 NVarchar 字段中即可。它速度更快,避免了所有转换错误并防止 SQL 注入攻击。

    【讨论】:

    • 不幸的是,我可以改变的东西非常有限。我很想完全接受 Unicode,但系统的一半是用 Visual C++ 4.2 编写的。我们还与一个复杂得多的系统共享一些代码,在该系统中,真正的 Unicode 转换在财务上是不可能的。我会接受你所说的,并尝试更好地诊断问题发生在哪里。
    猜你喜欢
    • 1970-01-01
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    • 2012-08-08
    • 1970-01-01
    • 2011-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多