2016-12-05 8 views
1

После нахождения bug in MySQL ODBC 5.3.6 у меня есть еще одна проблема, которая также возникает при использовании MySQL ODBC 5.3.4.«Неверное строковое значение» при вставке не-ASCII в базу данных MySQL с использованием ADODB в MS Access (VBA), но повторные работы

У меня есть приложение MS Access (Office 2016 ProPlus 32-bit), которое использует ADODB с MySQL ODBC (5.3.4 32-bit) для взаимодействия с локальным сервером базы данных MySQL (5.7.16 64-bit) на 64-разрядный компьютер Windows 10 Pro. Вставка символов, отличных от ASCII в базе данных MySQL, не выполняется с ошибкой «Неверное строковое значение», но если я снова попробую тот же оператор, оператор SQL будет правильно выполнен и правильное значение будет вставлено в таблицу базы данных!

Чтобы изолировать проблему, я создал следующую таблицу:

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

и тест базы данных MS Access, содержащие следующий VBA код (и ссылку на Microsoft ActiveX Data Objects 6.1 библиотеки):

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 

Соответствующие строки в my.ini:

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

Вот результаты тестов :

  1. Выполнение останавливается на заявлении .Execute с ошибкой 80004005: [MySQL] [ODBC 5.3 (ж) Driver] [туздЫ-5.7.16-журнал] Неверное значение строки: '\ xE8gh' для столбца ' имя "в строке 1;
  2. Если я продолжу отладку (F8), оператор SQL будет правильно выполнен и правильное значение будет вставлено в таблицу базы данных;
  3. Если я использую драйвер ODBC «ANSI» вместо драйвера «Unicode», этот тест выполняется впервые, но затем более сложные (например, китайские) символы, отличные от ASCII, заменяются вопросительными знаками;
  4. Я считаю, что VBA внутренне использует Unicode, но MySQL does not support UTF16 for clients и указание «charset = utf8mb4» в строке подключения ODBC или выполнить «SET CHARACTER SET utf8mb4» сначала не помогает, а «SET NAMES utf8mb4» не поддерживается;
  5. Если я использую INSERT IGNORE вместо INSERT, первое выполнение кажется успешным, но значение фактически усекается на «è» (поэтому вставлен только «abcd»);
  6. Это также происходит с ODBC MySQL 5.3.6

Могу ли я делать что-либо неправильно, или это еще одна ошибка в драйвере MySQL ODBC?

+0

Попробуйте 'dbParams.Type = adVarWChar' вместо' dbParams.Type = adVarChar'. –

+0

@GordThompson: ДЕЙСТВИТЕЛЬНО? просто одно письмо ?! Вы спасли мой день/неделю/месяц! Я пробовал всевозможные вещи, такие как character-set-client-handshake = FALSE, потому что я думал, что, возможно, первоначальное рукопожатие потерпело неудачу. Если вы добавите свой комментарий в качестве ответа, я могу выбрать его как лучший ответ, и, возможно, мы сможем помочь бедному дерну, который боролся в течение нескольких недель, как я. #ifeelstupid –

+0

Но по-прежнему странно, что он преуспевает во второй попытке (я проверил, но значение dbParams.Type не будет автоматически изменено). –

ответ

1

Заявление ...

dbParams.Type = adVarChar 

... говорит объект ADODB.Parameter, что его значение будет строка однобайтовых символов. Эти однобайтовые символы будут переданы драйверу ODBC, который, в свою очередь, передаст их в механизм базы данных MySQL. Если механизм базы данных ожидает символов UTF-8, тогда произойдет ошибка, потому что 0xE8 (è на многих страницах типа «latin-1», например Windows-1252) не является допустимой последовательностью байтов UTF-8.

Изменение выше заявление ...

dbParams.Type = adVarWChar 

... говорит ADODB.Объект параметра, что его значение будет представлять собой строку многобайтовых символов («Wide»). При присвоении значения, используя строку VBA буквального ...

dbParams.Value = "dèf" 

... ADODB преобразует строку из своего однобайтной представления (на основе текущей локали Windows) в Unicode, и передать в ODBC Водитель. Драйвер ODBC способен «переупаковать» строку из необработанного Unicode (U+0064 U+00E8 U+0066) в кодировку UTF-8 (0x64 0xC3 0xA8 0x66) и передать ее движку базы данных.