Внимание: MySQL считает, что буквы «ё» и «е» — одно и то же.

Увы, MySQL, если выбрать кодировку Unicode, считает, что «е» и «ё» — это одно и то же. Багом это не считается, в официальной таблице, где описано как MySQL 6.0 сравнивает символы, эти символы в одном ряду.
mysql> set names utf8 collate utf8_unicode_ci;
Query OK, 0 rows affected (0.00 sec)

mysql> select 'е'='ё', 'ё'='ѐ'\G
*************************** 1. row ***************************
'е'='ё': 1
'ё'='ѐ': 1
1 row in set (0.00 sec)
Самое печальное, это нелогичное поведение всплывает, если есть потребность перевести базу с CP1251 на UTF-8, так как в CP1251-то как раз всё хорошо:
mysql> set names cp1251;
Query OK, 0 rows affected (0.00 sec)

mysql> select 'е'='ё', 'ё'='ѐ'\G
*************************** 1. row ***************************
'е'='ё': 0
'ё'='ѐ': 0
1 row in set (0.00 sec)
Чем это может быть плохо? Например, у нас по какому-то текстовому полю имеется уникальный ключ. Для иллюстративности, пусть это будет словарь фамилий. Фамилии Рублев и Рублёв — разные, но MySQL так не считает (для простоты опускаю другие поля):
mysql> set names utf8 collate utf8_unicode_ci;
Query OK, 0 rows affected (0.00 sec)

mysql> create table surname(surname varchar(255) primary key);
Query OK, 0 rows affected (0.07 sec)

mysql> insert into surname values('Рублёв');
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> insert into surname values('Рублев');
ERROR 1062 (23000): Duplicate entry 'Рублев' for key 'PRIMARY'
Я придумал только один способ, исправляющий это поведение (но у него есть недостаток):
mysql> create table surname(surname varchar(255) primary key collate 'utf8_bin');
Query OK, 0 rows affected (0.02 sec)

mysql> insert into surname values('Рублёв');
Query OK, 1 row affected (0.00 sec)

mysql> insert into surname values('Рублев');
Query OK, 1 row affected (0.00 sec)

mysql> select * from surname where surname='рублев';
Empty set (0.00 sec)
Я выключил case insensitive у данного столбца, явным указанием «collate». Это полностью решает проблему с «ё», но лишает нас удовольствия искать, не заботясь о совпадении регистра.
31 января 2011 17:34

dinoel (инкогнито)
31 января 2011, 19:43

Интересно. А что вернёт
select * from surnames where LOWER(surname) = LOWER('Рублёв') ?

dinoel (инкогнито)
31 января 2011, 19:44

Кстати, заметил баг - если имя не вводить, то выдаст ошибку "введите имя или адрес блога" , но текст комментария пропадёт. Неприятно.

bolk (bolknote.ru)
31 января 2011, 20:47, ответ предназначен dinoel

Интересно. А что вернёт
select * from surnames where LOWER(surname) = LOWER('Рублёв')?
В каких условиях?
Кстати, заметил баг - если имя не вводить, то выдаст ошибку "введите имя или адрес блога" , но текст комментария пропадёт. Неприятно.
Да, я знаю, в TODO записан, но никак не пойдут руки поправить :( Но я поправлю.

dinoel (инкогнито)
31 января 2011, 21:53

В каких условиях?
create table surname(surname varchar(255) primary key collate 'utf8_bin');
вот в таких, т.е. при бинарном сравнении.
Хотя я догадываюсь :)

dinoel (инкогнито)
31 января 2011, 21:56

Проверил, работает как надо. Т.е. проблема с регистром решается просто

 select * from surname where LOWER(surname)=LOWER('рублев');
+--------------+
| surname |
+--------------+
| Рублев |
+--------------+
1 row in set (0.00 sec)

mysql> select * from surname where LOWER(surname)=LOWER('рублёв');
+--------------+
| surname |
+--------------+
| Рублёв |
+--------------+

dinoel (инкогнито)
31 января 2011, 21:57

Другое дело что с сортировкой будут проблемы..

bolk (bolknote.ru)
31 января 2011, 22:38, ответ предназначен dinoel

Другое дело что с сортировкой будут проблемы..
С сортировкой и использованием индекса.

besisland (besisland.name)
31 января 2011, 22:53

Я считаю, что подобное обращение с пользовательскими данными со стороны СУБД есть мерзость и грех великий. Кто ей разрешал брать на себя такую ответственность? Её дело — данные хранить.

dinoel (инкогнито)
31 января 2011, 23:45

Её дело — данные хранить.
А также сортировать, сравнивать и искать.

bolk (bolknote.ru)
1 февраля 2011, 00:30, ответ предназначен besisland (besisland.name):

Путать «е» и «ё» — точно великий грех. Это неудобно. В конце концов, кроме помощника кроссвордиста существует ещё множество других задач, которые хочется писать с использованием этой БД.

maxim-zotov (maxim-zotov.livejournal.com)
1 февраля 2011, 09:57

mysql поступает очень правильно. У "ё" давно нет прав, и не mysql их у неё отобрал, потакать желаниям считанных пуристов - это усложнять жизнь миллионам обычных людей, которые ищут и заносят в базы данных "Рублев" и "Ежик в тумане".

besisland (besisland.name)
1 февраля 2011, 11:26

Дело не в «е» и «ё», а в незапрашиваемых явно операциях над строками вообще.

besisland (besisland.name)
1 февраля 2011, 11:28, ответ предназначен dinoel

До сих пор из того факта, что MySQL по умолчанию сравнивает строки регистронезависимо или же приравнивает «ü» и «u», я выносил для себя только широкий спектр проблем, которые приходилось так или иначе решать.

Artjom Kurapov (kurapov.name)
2 февраля 2011, 01:12

BINARY() ?

bolk (bolknote.ru)
2 февраля 2011, 01:22, ответ предназначен Artjom Kurapov (kurapov.name):

Не понял.

Дмитрий (http://www.kains.ru) (инкогнито)
8 октября 2011, 15:42

Хм... Полезное однако иследование... Хотя, если честно, то ё редко где можно увидеть, все давно уже используют е заместо ё... Но опять таки с точки зрения русского языка правильнее будет именно ё...

bolk (bolknote.ru)
8 октября 2011, 16:51, ответ предназначен Дмитрию (http://www.kains.ru)

Например, в фамилиях и географических названиях нельзя без «ё».

NightFox (инкогнито)
11 августа 2016, 17:26

Решил проблему по примеру описаному здесь: http://www.sql.ru/forum/766045-2/besit-zhenyok-kodirovki-cp1251-utf8-bukva-yo?mid=11663963#11663963
А именно в /usr/share/mysql/charsets/Index.xml изменил
<charset name="utf8">
  <family>Unicode</family>
  <description>UTF-8 Unicode</description>
  <alias>utf-8</alias>
  <collation name="utf8_general_ci" id="33">
   <flag>primary</flag>
   <flag>compiled</flag>
  </collation>
  <collation name="utf8_bin" id="83">
    <flag>binary</flag>
    <flag>compiled</flag>
  </collation>
  <collation name="utf8_russian_ci" id="250">
    <rules>
      <reset>\u0415</reset><p>\u0401</p> <!-- ЕЁ -->
      <reset>\u0435</reset><p>\u0451</p> <!-- её -->
    </rules>
  </collation>
</charset>
и добавил:
<charset name="utf8mb4">
  <family>Unicode</family>
  <description>UTF-8 Unicode</description>
  <alias>utf-8</alias>
  <collation name="utf8mb4_russian_ci" id="251">
    <rules>
      <reset>\u0415</reset><p>\u0401</p> <!-- ЕЁ -->
      <reset>\u0435</reset><p>\u0451</p> <!-- её -->
    </rules>
  </collation>
</charset>
после чего выполнил:
ALTER TABLE `таблица` CHANGE `столбец` `столбец` тип CHARACTER SET utf8mb4 COLLATE utf8mb4_russian_ci NOT NULL DEFAULT '';

Ваше имя или адрес блога (можно OpenID):

Текст вашего комментария, не HTML:

Кому бы вы хотели ответить (или кликните на его аватару)