Предложение MySQL collate — до или после предложения like?

#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. Понял. Спасибо за информацию