Как заставить MySQL правильно обрабатывать UTF-8


102

Один из ответов на вопрос, который я задал вчера, предполагал, что я должен убедиться, что моя база данных может правильно обрабатывать символы UTF-8. Как я могу это сделать с MySQL?


4
Я действительно надеюсь, что мы получим исчерпывающий ответ, охватывающий различные версии MySQL, несовместимости и т. Д.
Эдвард З. Ян


1
@ EdwardZ.Yang - представлен MySQL 4.1 CHARACTER SETs; 5.1.24 испортил сопоставление немецких диез-s (ß), которое было исправлено добавлением другого сопоставления в 5.1.62 (возможно, что ухудшило положение); 5.5.3 заполнил utf8 новой кодировкой utf8mb4.
Рик Джеймс

1
Этот вопрос совершенно тот же, что и этот .. Пожалуйста, посмотрите этот stackoverflow.com/questions/3513773/…
Nyein Aung

Стоит отметить, что большинство из этих ответов просто неверны. Не использовать utf8. Он поддерживает только символы длиной до 3 байтов. Правильный набор символов, который вы должны использовать в MySQL, - это utf8mb4.
Брендан Берд,

Ответы:


89

Обновить:

Краткий ответ - вы почти всегда должны использовать utf8mb4кодировку и utf8mb4_unicode_ciсопоставление.

Чтобы изменить базу данных:

ALTER DATABASE dbname CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Видеть:

Оригинальный ответ:

MySQL 4.1 и выше имеет набор символов по умолчанию UTF-8. Вы можете проверить это в своем my.cnfфайле, не забудьте установить и клиент, и сервер ( default-character-setи character-set-server).

Если у вас есть данные, которые вы хотите преобразовать в UTF-8, сделайте дамп своей базы данных и импортируйте ее обратно как UTF-8, убедившись, что:

  • использовать SET NAMES utf8перед запросом / вставкой в ​​базу данных
  • использовать DEFAULT CHARSET=utf8при создании новых таблиц
  • на этом этапе ваш клиент и сервер MySQL должны быть в UTF-8 (см. my.cnf). помните, что любые используемые вами языки (например, PHP) также должны быть UTF-8. Некоторые версии PHP будут использовать собственную клиентскую библиотеку MySQL, которая может не поддерживать UTF-8.

Если вы действительно хотите перенести существующие данные, не забудьте сначала сделать резервную копию! Когда что-то пойдет не так, как планировалось, может произойти много странного измельчения данных!

Некоторые ресурсы:


29
Насколько я понимаю, utf8MySQL относится только к небольшому подмножеству полного Unicode. utf8mb4Вместо этого вы должны использовать полную поддержку. См. Mathiasbynens.be/notes/mysql-utf8mb4 «В течение долгого времени я использовал кодировку MySQL utf8 для баз данных, таблиц и столбцов, предполагая , что она сопоставлена ​​с описанной выше кодировкой UTF-8».
Аарон МакДэйд

7
В MySQL никогда не было набора символов по умолчанию UTF-8. 4,1 и 5.x до последней 5.7 все используют latin1и latin1_swedish_ciдля кодировки и сортировки по умолчанию. См. Страницу «Набор символов сервера и сопоставление» в руководстве по MySQL для подтверждения: dev.mysql.com/doc/refman/5.1/en/charset-server.html
Animism

2
@TimTisdall Вам не нужно беспокоиться о utf8mb4дополнительной памяти, когда большая часть текста - это ASCII. Несмотря на то, что charстроки выделяются заранее, varcharстроки нет - см. Последние несколько строк на этой странице документации . Например, char(10)будет пессимистично зарезервировать 40 байтов под utf8mb4, но varchar(10)выделить байты в соответствии с кодировкой переменной длины.
Кевин А. Науде,

1
@ Кевин, я думаю, ты неправильно это понял. Думаю, максимальная длина строки - 64 КБ. Вы можете сделать поле utf8mb4 только 1/4 от этого, потому что оно должно было зарезервировать это количество места. Таким образом, даже если это ASCII, вы можете вставить только 16k символов.
Тим Тисдалл,

1
@TimTisdall О, ты говоришь о верхних границах. Да, те ниже. К счастью, текущие версии mysql будут автоматически обновляться varchar(n)до этого textтипа данных, если вы попытаетесь изменить значение varchar(n)поля на размер больше допустимого байта (при выдаче предупреждения). Индекс также будет иметь нижнюю верхнюю границу наихудшего случая, и это может вызвать другие проблемы.
Кевин А. Науде

44

Чтобы сделать это «постоянным», в my.cnf:

[client]
default-character-set=utf8
[mysqld]
character-set-server = utf8

Чтобы проверить, зайдите в клиент и покажите несколько переменных:

SHOW VARIABLES LIKE 'character_set%';

Убедитесь, что они все utf8, кроме того ..._filesystem, что должно быть binaryи ..._dir, что указывает где-то в установке MySQL.


В моем случае это не сработало, но я все равно создал файл my.cf в / etc с заданным содержимым. Я использовалcreate table my_name(field_name varchar(25) character set utf8);
Marek Bar

"ПОКАЗАТЬ ПЕРЕМЕННЫЕ КАК 'character_set%';" команда выявила мне проблему с моим подключением. Спасибо!
javsmo 05

1
Это не так. MySQL не называет utf8"полным" UTF-8.
TWR Cole

32

MySQL 4.1 и выше имеет вызываемый по умолчанию набор символов, utf8но на самом деле это только подмножество UTF-8 (допускает только трехбайтовые символы и меньше).

Используйте в utf8mb4качестве кодировки, если хотите "полный" UTF-8.


5
Однозначно согласен, это единственно правильный ответ. utf8не включает символы, такие как смайлы. utf8mb4делает. Проверьте это для получения дополнительной информации о том, как обновить: mathiasbynens.be/notes/mysql-utf8mb4
jibai31,

@Basti - в основном правильно (до недавнего времени по умолчанию использовался latin1), но не полный (не обсуждается правильная вставка / выбор данных в кодировке utf8 и отображение в html).
Рик Джеймс

С уважением, @RickJames, Басти сказал «пока» - я не помню, чтобы видел ваш ответ, когда я это размещал.
TWR Cole

Увы, существует около 5 четко различающихся симптомов проблем с utf8 и около 4 вещей, которые программисты делают неправильно, чтобы вызвать проблемы. Большинство ответов указывают только на одну вещь, которая может нуждаться в исправлении. Первоначальный вопрос был широким, поэтому для ответа требовалось все 4. Возможно, Басти был знаком с одним симптомом, решением которого был ваш единственный аспект.
Рик Джеймс

8
В качестве отступления я хотел бы сделать паузу и внимательно взглянуть на команду MySQL. о_о вы что, ребята думали? Вы понимаете, сколько путаницы вы посеяли, создав в своей программе кодовую страницу под названием «utf8», которая на самом деле не является UTF-8? Проклятые придурки. </rant>
TWR Cole

20

Краткий ответ: Используйте utf8mb4в 4 местах:

  • Байты в вашем клиенте - это utf8, а не latin1 / cp1251 / etc.
  • SET NAMES utf8mb4 или что-то подобное при установке клиентского подключения к MySQL
  • CHARACTER SET utf8mb4 во всех таблицах / столбцах, кроме столбцов, которые имеют строго ascii / hex / country_code / zip_code / и т. д.
  • <meta charset charset=UTF-8>если вы выводите в HTML. (Да, здесь другое написание.)

Больше информации ;
UTF8 полностью

Вышеупомянутые ссылки предоставляют «подробный канонический ответ, необходимый для решения всех проблем». - На этом форуме есть ограниченное пространство.

редактировать

В дополнение к тому, что в нем CHARACTER SET utf8mb4содержатся «все» символы мира, COLLATION utf8mb4_unicode_520_ciможно утверждать, что это «лучшее универсальное» сопоставление для использования. (Есть также сопоставления на турецком, испанском и т. Д. Для тех, кому нужны нюансы на этих языках.)


Моя новая ссылка о том, как отлаживать проблемы с utf8 из полученного вами вывода.
Рик Джеймс

Почему unicode_520_ci не самый лучший: stackoverflow.com/a/49982378/62202
Луи

@Louis - И, как я подразумевал, испанские и турецкие (а также польские) пользователи могут быть недовольны. «Лучшее многоборье» имеет тенденцию причинять боль каждому. MySQL 8.0 имеет еще более новую «лучшую» сортировку: utf8mb4_0900_ai_ci . Увы, снова L = Ł.
Рик Джеймс

4

Кодировка - это свойство базы данных (по умолчанию) и таблицы. Вы можете посмотреть (команды MySQL):

show create database foo; 
> CREATE DATABASE  `foo`.`foo` /*!40100 DEFAULT CHARACTER SET latin1 */

show create table foo.bar;
> lots of stuff ending with
> ) ENGINE=InnoDB AUTO_INCREMENT=252 DEFAULT CHARSET=latin1

Другими словами; Проверить кодировку базы данных или изменить ее довольно легко:

ALTER TABLE `foo`.`bar` CHARACTER SET utf8;

1
Это не так. MySQL не называет utf8"полным" UTF-8.
TWR Cole

3

Чтобы изменить кодировку набора символов на UTF-8 для самой базы данных, введите следующую команду в командной строке mysql>. ИСПОЛЬЗОВАНИЕ ALTER DATABASE.. Замените DBNAME именем базы данных:

ALTER DATABASE DBNAME CHARACTER SET utf8 COLLATE utf8_general_ci;

Это дубликат этого вопроса. Как преобразовать весь набор символов и сопоставление базы данных MySQL в UTF-8?


2

Я последовал решению Хавьера, но добавил несколько других строк в my.cnf:

[myslqd]
skip-character-set-client-handshake
collation_server=utf8_unicode_ci
character_set_server=utf8 

Я нашел эту идею здесь: http://dev.mysql.com/doc/refman/5.0/en/charset-server.html в первом / единственном комментарии пользователя внизу страницы. Он упоминает, что рукопожатие клиента с пропуском набора символов имеет некоторое значение.


Этот нелюбимый ответ без голосования был единственным, что мне помогло! Так что он получает мой голос, это совершенно точно. skip-character-set-client-handshakeбыл ключом.
Маркус


0

Установите свой , database collationчтобы UTF-8 затем применить table collationк невыполнению базы данных.


-1

Ваш ответ: вы можете настроить MySql Settings. В «Моем ответе» может быть что-то вырванное из контекста, но это также поможет вам.
как настроить Character SetиCollation .

Для приложений, которые хранят данные с использованием набора символов MySQL по умолчанию и функции сопоставления ( latin1, latin1_swedish_ci), не требуется специальной настройки. Если приложениям требуется хранение данных с использованием другого набора символов или сопоставления, вы можете настроить информацию о наборе символов несколькими способами:

  • Укажите параметры символов для каждой базы данных. Например, приложениям, использующим одну базу данных, может потребоваться utf8, тогда как приложениям, использующим другую базу данных, может потребоваться sjis.
  • Укажите параметры символов при запуске сервера. Это заставляет сервер использовать данные настройки для всех приложений, которые не делают других договоренностей.
  • Укажите параметры символов во время конфигурации , если вы собираете MySQL из исходников. Это заставляет сервер использовать данные настройки для всех приложений без необходимости указывать их при запуске сервера.

Примеры, показанные здесь для вашего вопроса, чтобы установить набор символов utf8, здесь также установите сопоставление для большей полезности ( utf8_general_ciсопоставление`).

Укажите параметры символов для каждой базы данных

  CREATE DATABASE new_db
  DEFAULT CHARACTER SET utf8
  DEFAULT COLLATE utf8_general_ci;

Укажите параметры персонажа при запуске сервера

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci

Укажите параметры символов во время конфигурации MySQL

shell> cmake . -DDEFAULT_CHARSET=utf8 \
           -DDEFAULT_COLLATION=utf8_general_ci

Чтобы увидеть значения системных переменных набора символов и сопоставления, которые применяются к вашему соединению, используйте эти операторы:

SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';

Это может быть длинный ответ, но есть все способы, которыми вы можете воспользоваться. Надеюсь, мой ответ будет вам полезен. для получения дополнительной информации http://dev.mysql.com/doc/refman/5.7/en/charset-applications.html


-2

SET NAMES UTF8

Это трюк


2
Хотя использование SET NAMES UTF8(или UTF8mb4) является правильным, вы не объясняете, что он делает (набор символов, используемый для этого соединения). «Это помогает» звучит так, как будто это решит проблему (заставить MySQL правильно обрабатывать UTF-8), но многие базы данных MySQL по умолчанию настроены на latin1, так что это не будет правильным решением. Я бы изменил кодировку по умолчанию и таблицы на utf8mb4. На самом деле, этот ответ довольно неполный, поэтому я проголосовал против.
basic6

-2

ПОДКЛЮЧЕНИЕ БАЗЫ ДАННЫХ К UTF-8

$connect = mysql_connect('$localhost','$username','$password') or die(mysql_error());
mysql_set_charset('utf8',$connect);
mysql_select_db('$database_name','$connect') or die(mysql_error());

-3

Установите соединение с базой данных в UTF8:

  if($handle = @mysql_connect(DB_HOST, DB_USER, DB_PASS)){          
         //set to utf8 encoding
         mysql_set_charset('utf8',$handle);
  }

Если вы используете PHP, не используйте устаревший mysql_*интерфейс. Переключитесь на mysqli_*или PDO.
Рик Джеймс

-3

Смогла найти решение. Выполните следующее, как указано на http://technoguider.com/2015/05/utf8-set-up-in-mysql/

SET NAMES UTF8;
set collation_server = utf8_general_ci;
set default-character-set = utf8;
set init_connect = SET NAMES utf8′;
set character_set_server = utf8;
set character_set_client = utf8;

Последние две строки являются избыточными, поскольку первая уже включает их: dev.mysql.com/doc/refman/5.0/en/charset-connection.html
DanielM

Тоже не полное решение. Колонны нужны CHARACTER SET utf8. rootне выполнит самого важного init_connect.
Рик Джеймс
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.