(Обновление: найден обходной путь, добавлен в конец оригинального вопроса здесь - но почему обходной путь работает / необходим?)
Я только что обновил свою базу данных для поддержки UTF-8и этот SQL не выполняется при вызове из PHP:
SELECT ID FROM people WHERE Email = 'myemail@example.com' AND md5(PasswordHashed) = '26Ba48f4df2dba59b00d80c4c09a90e78'
Сообщение об ошибке: Недопустимое сочетание параметров сортировки (utf8mb4_unicode_ci, COERCIBLE) и (utf8mb4_general_ci, COERCIBLE) для операции'='
SQL работает FINE, когда я вставляю его прямо в клиент mysqld. Так что я думаю, что это связано с тем, как PHP подключается к базе данных. Код для установления соединения прост:
$this->dbc = mysqli_connect( null, 'myuser', '', 'mytable', 0, '/var/lib/mysql/mysql.sock' );
if ( $this->dbc ) {
$this->dbc->set_charset( "utf8mb4" );
$this->dbc->query( 'SET collation_connection = utf8mb4_unicode_ci;' );
}
И все же он не работает. (Насколько я вижу, все другие запросы SQL в коде работают нормально, так что это очень странно.)
Подтверждено, что с существующими параметрами сортировки все в порядке:
Сортировка самой базы данных - utf8mb4_unicode_ci (подтверждено с помощью SELECT @@collation_database;
)
Сортировка на самой таблице - utf8mb4_unicode_ci (подтверждено с помощью show table status;
)
И show full columns from people;
подтверждает, что:
Email
- это varchar (70) с сопоставлением utf8mb4_unicode_ci PasswordHashed
- это varchar (255) с сопоставлением utf8mb4_unicode_ci ID
- это int (10) без знака без сопоставления
В моей базе данных файл my.cnf содержит следующее:
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
(Я также добавил и удалил character-set-client-handshake=FALSE
из файла my.cnf,как упоминалось в некоторых других постах. Без изменений.)
Как ни странно, в сообщении об ошибке упоминается utf8mb4_ general _ci, но я не могу найти что-либо , для которого установлено это значение. сверка. Все, что я могу найти, чтобы проверить это utf8mb4_unicode_ci, и я трижды проверил это.
Я запустил mysqlcheck
, чтобы восстановить таблицы, и перезапустил сервер тоже. Я выкинул всю таблицу и повторно импортировал ее (думая, что перестройка таблицы и ее индексов с нуля поможет). Ничего из этого не помогает.
Я бегу mariadb Ver 15.1 Distrib 10.4.8-MariaDB, for Linux (x86_64) using readline 5.1
Итак ... что происходит? !! Почему я получаю это сообщение об ошибке и почему он думает, что что-то utf8mb4_general_ci?
ОБНОВЛЕНИЕ: найдено решение, но почему?
Код, которыйПри возникновении ошибки используются подготовленные операторы mysqli, поэтому это выглядит так:
$sql = "SELECT ID FROM people
WHERE Email = ? AND
MD5(PasswordHashed) = ?";
...prepare SQL...
...bind SQL parameters...
...execute()...
Я изменил его на:
$sql = "SELECT ID FROM people
WHERE Email = ? AND
CAST(MD5(PasswordHashed) AS
CHAR CHARACTER SET utf8mb4) = ?";
И теперь он работает нормально. ?? !!?
Так что я думаю, что это проблема того, как PHP-класс mysqli работает с драйвером mysql. Как я уже упоминал выше, оригинальный SQL отлично работает, когда я «готовлю» его вручную и просто вставляю в командную строку mysql ... так что я действительно не думаю, что он имеет какое-либо отношение к кодировке или сопоставлению в любой точке,Я думаю, что это какая-то странная ошибка, когда подготовленная переменная, вставляемая классом mysqli, использовала странный набор символов / сопоставление.
Но: также обратите внимание, что в исходном сообщении об ошибке содержалась жалоба на сопоставление, ноМой обходной путь исправил проблему, применяя набор символов (не сопоставление). Очень странно.
Почему мой обходной путь удался? Это где-нибудь задокументировано? Это ошибка PHP?