0

我正在开发与远程 MariaDB 数据库通信的 Delphi 应用程序(通过 ADO 和 ODBC 驱动程序)。发现在某些计算机上无法将 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
Charset is utf8, collat​​e - 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;
4

1 回答 1

2

您必须定义客户端和数据库之间通信的编码。如果您不这样做,那么数据库会采用一种编码,而客户端可能会采用不同的编码。很可能较旧的安装默认不使用 UTF-8。仅仅因为您的所有数据库表都是使用 Unicode 字符集和排序规则定义的,这并不意味着写入和读取这些数据表的数据以相同的编码进行通信。

  • MySQLSET NAMES一次设置多个变量的便捷方式。使用类似的编码utf8不会转换任何东西 - 它告诉数据库解释该编码中的所有传入字节(并在为所有结果发送字节时使用该编码)。
  • PHPmysqli_set_charset()内部也在做同样的事情,但是提供了这个函数来让你知道你对其他方便函数的选择(例如mysqli_real_escape_string())。

在您确定通信实际上是在 UTF-8 中发生之后,只剩下您的客户端本身:如果您交出 Delphi,驱动程序是否会为您进行转换Widestring?或者您是否必须提供实际的 UTF-8 编码字节作为查询?链接不是为了好玩:文档告诉您足够的事实可以检查和测试-无需质疑它们并做出疯狂的假设-只会使您理解错误。

于 2021-06-10T21:53:44.777 回答