Unicode转换,数据库困境(Delphi 2007到XE2)

时间:2012-05-11 12:41:57

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

目前,我正在将所有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?

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

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

1 个答案:

答案 0 :(得分:2)

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

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

BTW,您的select语句在字段中存储ASCII值。如果要将值存储为unicode值,则必须在N前面添加值,例如g.g

SELECT id FROM table WHERE name = N'something'

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

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