问题描述
我正在开发与远程 MariaDB 数据库(通过 ADO 和 ODBC 驱动程序)通信的 Delphi 应用程序。发现在某些计算机上无法将 Cyrillic 字符串添加到 DB。像这样的错误信息:
[MysqL][ODBC 8.0(w) Driver][MysqLd-5.5.5-10.3.29-MariaDB]Incorrect string value: '\xC2\xC2\xC8 \xF1\xE8…' for column <here's target tables and columns name> at row 1
字符集为 utf8
,整理 - utf8_bin
。它在我装有 Windows 10 的计算机上完美运行,但在装有 Windows 8 和 Vista 的计算机上会出错。因此,据我了解,问题不在数据库设置中,而在操作系统中。它可以是什么?也许是区域设置之类的?
更新
表格:
SHOW CREATE TABLE equip;
CREATE TABLE `equip` (
`eqid` int(10) unsigned NOT NULL AUTO_INCREMENT,`eqname` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'Наименование оборудования',PRIMARY KEY (`eqid`),UNIQUE KEY `eqname_UNIQUE` (`eqname`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
连接到数据库:
procedure OpenDBConnection;
begin
dmMain.dbConnection.Connected := False;
dmMain.dbConnection.ConnectionString := Format(
'Driver={MysqL ODBC 8.0 Unicode Driver};Port=%s;Server=%s;Database=%s;User=%s;Password=%s;',[Port,Server,Database,User,Password]);
dmMain.dbConnection.Connected := True;
end;
向数据库插入数据:
const
tblEquip = 'equip';
colEquipName = 'eqname';
queryInsertEquipment =
' INSERT INTO ' + tblEquip + '(' +
colEquipName + ') ' +
'VALUES(:' +
colEquipName + '); ';
function TdmMain.AddEquipment(const Equip: TEquipment;
const RefreshEquipmentListDataSet: Boolean): Integer;
begin
Result := 0;
try
cmdTemp.CommandText := queryInsertEquipment;
cmdTemp.Parameters.ParamByName(colEquipName).Value := Equip.Name;
cmdTemp.Execute;
Result := GetLastID;
if RefreshEquipmentListDataSet then
RefreshDataSet(dsetEquipment,colEquipID,Result);
except on E: Exception do
fmMessage.ShowMessage(msgErrorAddEquipment,mtError);
end;
end;
解决方法
您必须定义客户端和数据库之间的通信编码。如果不这样做,则数据库会采用一种编码,而客户端可能会采用不同的编码。默认情况下,较旧的安装很可能不使用 UTF-8。仅仅因为您的所有数据库表都是用 Unicode 字符集和排序规则定义的,并不意味着写入和读取这些表的数据以相同的编码进行通信。
-
MySQL 的
SET NAMES
是一次设置多个变量的便捷方式。使用像utf8
这样的编码不会转换任何东西 - 它告诉数据库解释该编码中的所有传入字节(并在为所有结果发送字节时使用该编码)。 -
PHP 的
mysqli_set_charset()
在内部做同样的事情,但提供这个函数也是为了让你知道你对其他方便的函数(例如mysqli_real_escape_string()
)的选择。立>
在您确定实际以 UTF-8 进行通信后,只剩下您的客户端本身:如果您交出 Delphi Widestring
,驱动程序是否会为您进行转换?或者您是否必须提供实际的 UTF-8 编码字节作为您的查询?这些链接不是为了好玩:文档告诉你足够多的事实,可以检查和测试 - 没有必要质疑它们并做出疯狂的假设 - 只会让你理解错误。