在MS Access(VBA)中使用ADODB将非ASCII插入MySQL数据库时"Incorrect string value",但重试有效



在MySQL ODBC 5.3.6中发现错误后,我遇到了另一个问题,使用MySQL ODBC 5.3.4也会发生。

我有一个 MS Access 应用程序(Office 2016 ProPlus 32 位),它使用 ADODB 和 MySQL ODBC(5.3.4 32 位)连接到 Windows 10 Pro 64 位计算机上的本地 MySQL 数据库服务器(5.7.16 64 位)。在 MySQL 数据库中插入非 ASCII 字符失败,并显示错误"字符串值不正确",但如果我再次尝试相同的语句,SQL 语句将正确执行,并将正确的值插入数据库表中!

为了隔离问题,我创建了下表:

CREATE TABLE test2 (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(100) CHARACTER SET utf8mb4,
PRIMARY KEY (id));

以及包含以下 VBA 代码(以及对 Microsoft ActiveX 数据对象 6.1 库的引用)的测试 MS Access 数据库:

Public Function dbTestIt2() as Long
Dim dbConn As New ADODB.Connection
Dim dbCmd As New ADODB.Command
Dim dbParams As New ADODB.Parameter
Dim l As Long
dbConn.ConnectionString = "Driver={MySQL ODBC 5.3 Unicode Driver};option=3;database=xxx;user=yyy;password=zzz;"
dbConn.Open
With dbCmd
.ActiveConnection = dbConn
.CommandType = adCmdText
.CommandText = " INSERT INTO test2 (name) VALUES (?);"
dbParams.Type = adVarChar
dbParams.Size = 100
dbParams.Value = "abcdèfgh"
dbParams.Direction = adParamInput
.Parameters.Append dbParams
.Execute l, , adExecuteNoRecords
End With
dbConn.Close
dbTestIt2 = l
End Function

我的.ini中的相关行:

[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci

以下是测试结果:

  1. 执行在 处停止。执行错误80004005语句:[MySQL][ODBC 5.3(w) 驱动程序][mysqld-5.7.16-log]字符串值不正确:第 1 行"name"列的"\xE8gh";
  2. 如果我继续调试(F8),SQL语句将正确执行,并将正确的值插入到数据库表中;
  3. 如果我使用"ANSI"ODBC 驱动程序而不是"Unicode"驱动程序,则此测试第一次成功,但随后更复杂的(例如中文)非 ASCII 字符被问号替换;
  4. 我相信 VBA 在内部使用 Unicode,但 MySQL 不支持客户端的 UTF16,并且在 ODBC 连接字符串中指定"charset=utf8mb4"或先执行"SET CHARACTER SET utf8mb4"无济于事,不支持"设置名称 utf8mb4";
  5. 如果我使用 INSERT IGNORE 而不是 INSERT,第一次执行似乎成功了,但该值实际上在"è"处被截断(因此只插入了"abcd");
  6. 它也发生在MySQL ODBC 5.3.6中。

我做错了什么还是这是MySQL ODBC驱动程序中的另一个错误?

语句...

dbParams.Type = adVarChar

。正在告诉ADODB。参数对象,其值将是单字节字符的字符串。这些单字节字符将传递给 ODBC 驱动程序,而 ODBC 驱动程序又会将它们传递给 MySQL 数据库引擎。如果数据库引擎需要 UTF-8 字符,则会发生错误0xE8因为(在许多"拉丁 1"类型代码页(如 Windows-1252 中è)不是有效的 UTF-8 字节序列。

将上述语句更改为...

dbParams.Type = adVarWChar

。告诉ADODB。参数对象,其值将是多字节("宽")字符的字符串。使用 VBA 字符串文本分配值时...

dbParams.Value = "dèf"

。ADODB 会将字符串从其单字节表示形式(基于当前 Windows 区域设置)转换为 Unicode,并将其传递给 ODBC 驱动程序。ODBC驱动程序能够将原始Unicode(U+0064 U+00E8 U+0066)中的字符串"重新打包"为UTF-8编码(0x64 0xC3 0xA8 0x66),并将其传递给数据库引擎。

相关内容

  • 没有找到相关文章

最新更新