【发布时间】:2018-10-29 21:49:12
【问题描述】:
我有一个使用 Firebird SQL 导致错误的简单示例。
我有一个表,其中包含一个名为 Details 的列,其定义为:
DETAILS varchar(261) COLLATE UNICODE
如果我尝试执行以下查询:
SELECT a.DETAILS
FROM MODHISTORY a
WHERE
a.DETAILS LIKE '%Â%'
我得到错误:
Error: *** IBPP::SQLException ***
Context: Statement::Prepare( SELECT a.DETAILS
FROM MODHISTORY a
WHERE
a.DETAILS LIKE '%Â%'
)
Message: isc_dsql_prepare failed
SQL Message : -104
Invalid token
Engine Code : 335544849
Engine Message :
Malformed string
如果我在连接字符串中使用 CHARSET=UTF8 连接到数据库,此错误就会消失,但不幸的是,在连接到数据库时我不能使用 UTF8 作为字符集,因为其他一些表包含,例如:
SampleData blob sub_type 1 CHARACTER SET ASCII,
【问题讨论】:
-
列具有不同字符集的事实并不意味着您不能使用 UTF8 作为连接字符集。但是,您现在使用什么连接字符集?该错误表明您使用的是连接字符集 NONE,查询字符串
Â被编码为 - 例如 - WIN1252,然后尝试将这些原始字节转换为 UTF8,这不起作用,因为字节编码WIN1252 中的Â在UTF8 中无效。 -
尝试使用参数而不是字符串文字?或者尝试使用二进制文字? firebirdsql.org/refdocs/langrefupd25-hexbinstrings.html // 但正确的方法仍然是在与列的
UNICODE排序兼容的字符集中进行连接 -
如果我将字符集 UTF8 添加到我的连接字符串中,我在尝试保存 blob 数据时会出错。现在我们没有在连接字符串中指定字符集。有什么方法可以在我的 SELECT 语句中指定字符集?这能解决我的问题吗?
-
如何使用参数而不是字符串文字。有人可以举个例子吗?
-
如果您在连接编码中遇到错误,那么您将非 ascii 值保存到那些 blob 中(ASCII 仅定义字节 0..127 的字符),在使用连接字符集 NONE 时会被忽略(因为这会禁用很多字符集检查),或者您的代码/客户端组件在填充 blob 时做错了什么。您可以尝试使用介绍人语法。例如,如果您的默认编码是 Cp1252,请尝试使用 `LIKE _win1252'%Â%'。请注意,只有当发送到 Firebird 的字节实际上是该编码时,这才能正常工作,否则您可能会得到错误的字符。