#mysql #sql-like #collation
#mysql #sql-подобный #сопоставление
Вопрос:
Я работаю над переносом наших баз данных с utf8 (utf8mb3) на utf8mb4 (в рамках подготовки к окончательному переходу на MySQL 8), и из-за характера системы и количества баз данных и хостов я не могу сделать это одним выстрелом. Итак, я пытаюсь выяснить, будет ли сначала переносить базы данных (по одному за раз), прежде чем приложение будет работать нормально.
Пробуя это, я столкнулся со следующей ситуацией и хотел получить мнение эксперта о том, какой рекомендуемый способ сделать это и почему.
Информация о MySQL:
- версия — 5.7.30-33
- innodb_version — 5.7.30-33
- version_comment — Percona Server (GPL), выпуск 33, редакция 6517692
- character_set_client — utf8
- character_set_connection — utf8
- character_set_database — utf8mb4
- collation_connection — utf8_general_ci
- collation_database — utf8mb4_general_ci
У меня есть таблица (показать создать таблицу)
CREATE TABLE `mb4table1` (
`name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
со значениями
mysql> select * from mb4table1;
------ ------
| name | age |
------ ------
| abc | 43 |
| one | 41 |
| two | 42 |
------ ------
3 rows in set (0.00 sec)
С этой таблицей и данными,
(1) если я выполняю запрос
mysql> select * from mb4table1 where name like 'Abc';
Empty set (0.00 sec)
Конечно, он не находит никакой записи.
(2) Если я сделаю это
mysql> select * from mb4table1 where name like 'Abc' collate utf8_general_ci;
------ ------
| name | age |
------ ------
| abc | 43 |
------ ------
1 row in set (0.00 sec)
он может найти запись для abc.
(3) В то время как, если я перемещаю предложение сортировки,
mysql> select * from mb4table1 where name collate utf8_general_ci like 'Abc';
ERROR 1253 (42000): COLLATION 'utf8_general_ci' is not valid for CHARACTER SET 'utf8mb4'
(4) И, если я использую сопоставление utf8mb4, тогда оно работает нормально
mysql> select * from mb4table1 where name collate utf8mb4_general_ci like 'Abc';
------ ------
| name | age |
------ ------
| abc | 43 |
------ ------
1 row in set (0.00 sec)
Мой вопрос в том, в чем разница между (2) и (3)? Запрос (2), по-видимому, применил предложение collate и вернул ожидаемый результат. И, если мне придется использовать (3), как мне заставить его работать?
Примечание: сопоставление столбцов должно остаться. Только в паре запросов из 10 может потребоваться использовать предложение collate для выполнения поиска без учета регистра.
Комментарии:
1. ‘abc’ является неадекватным примером — он кодируется и сравнивается одинаково практически во всех наборах символов и сопоставлениях.
2. В какой момент вы меняете кодировку и параметры сортировки, связанные с соединениями ? Это то, что управляет литералом
'Abc'
3. @RickJames Сопоставление соединений устанавливается при установлении соединения (JDBC connectionCollation=utf8_general_ci)
4.Для поэтапного ввода имейте это в виду… Параметры соединения указывают кодировку в клиенте. В определениях столбцов указывается кодировка в таблице. Они не обязательно должны быть одинаковыми.
INSERT
иSELECT
(etc) преобразует (если возможно) по мере передачи текста между клиентом и базой данных.5. И… Мне неясно, когда литералы (например, ‘abc’) нуждаются в преобразовании. Еще одна вещь, которую можно сделать:
_utf8mb4'abc'
это способ присвоить литералу определенную кодировку.
Ответ №1:
Пока mysql не удалил его, и я не думаю, что это возможно в любом случае
Вы можете проверить с помощью
SHOW COLLATION WHERE Charset = 'utf8mb4';
Какие сопоставления поддерживаются
и в https://dev.mysql.com/doc/refman/8.0/en/charset-mysql.html вы можете увидеть все utf8mb4_
это в самом начале.
Если вы хотите углубиться. вы можете начать с https://dev.mysql.com/doc/refman/8.0/en/charset-charsets.html
'Abc' collate utf8_general_ci
Это utf8_general_ci
относится к строке ‘Abc’, которая не содержит uf8mb4 (4 байта) символов и может быть легко преобразована в это значение.
name collate utf8_general_ci
Это utf8_general_ci
относится к имени столбца, которое имеет значение uf8mb4 (4 байта) и не может быть преобразовано в это сопоставление, поскольку оно не поддерживается (см. Выше)
Комментарии:
1. Спасибо. Я это понимаю. Но мой вопрос заключается в том, почему одно и то же сопоставление на основе utf8 (utf8_general_ci) отлично работает в (2), но не в (3).
2. Понял. Спасибо за информацию