Як правильно MySQL обробляти UTF-8


102

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


4
Я дуже сподіваюся, що ми отримаємо вичерпну відповідь, що охоплює різні версії MySQL, несумісність тощо.
Edward Z. Yang,


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 / ...
Наїн Аунг

Варто зазначити, що більшість із цих відповідей є просто неправильними. Не використовуйте 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
Я розумію, що utf8в MySQL мається на увазі лише невеликий підмножина повного Unicode. utf8mb4Натомість вам слід скористатися повною підтримкою. Див. Mathiasbynens.be/notes/mysql-utf8mb4 "Тривалий час я використовував схему utf8 MySQL для баз даних, таблиць та стовпців, припускаючи , що він відображений у кодуванні UTF-8, описаному вище."
Аарон Макдейд

7
MySQL ніколи не мав набір символів за замовчуванням UTF-8. 4.1 і 5.x до останнього 5.7 для використання latin1та latin1_swedish_ciдля діаграми та порівняння за замовчуванням. Перегляньте сторінку "Набір символів сервера та їх зібрання" в посібнику MySQL: dev.mysql.com/doc/refman/5.1/uk/charset-server.html
Анімізм

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

1
@Kevin Я думаю, що ти це неправильно прочитав. Я думаю, що максимальна довжина рядка - 64 к. Ви можете зробити поле utf8mb4 лише на 1/4, тому що для цього потрібно було резервувати таку кількість місця. Тож навіть якщо це ASCII, ви можете вставити лише 16 к символів.
Тім Тісдалл

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

"SHOW VARIABLES LIKE 'character_set%';" команда виявила мені проблему з моїм з'єднанням. Дякую!
javsmo

1
Це неправильно. Що закликає MySQL utf8, не є "повним" UTF-8.
TWR Коул

32

MySQL 4.1 і вище має набір символів за замовчуванням, який він викликає utf8 але насправді лише підмножина UTF-8 (дозволяє лише трибайтові символи та менші).

Використовуйте utf8mb4як свою гарнітуру, якщо хочете "повний" UTF-8.


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

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

З повагою, @RickJames, Басті сказала "поки що" - я не пам'ятаю, як бачила вашу відповідь, коли я публікувала це.
TWR Коул

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

8
В сторону, я хотів би зробити паузу на мить і дати команді MySQL дійсно гарний, жорсткий погляд. o_o WTF ви думали, хлопці? Ви усвідомлюєте, скільки плутанини ви посіяли, створивши у своїй програмі кодову сторінку під назвою "utf8", яка насправді не є UTF-8? Прокляті мудаки. </rant>
TWR Коул

20

Коротка відповідь: Використовуйте utf8mb4в 4 місцях:

  • Байти вашого клієнта - utf8, а не latin1 / cp1251 / тощо.
  • 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 Коул

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/uk/charset-applications.html


-2

SET NAMES UTF8

Це робить трюк


2
Хоча правильне використання SET NAMES UTF8(або UTF8mb4) ви не пояснюєте, що це робить (набір символів, використовуваний для цього з'єднання). "Цей трюк" здається, що він вирішить проблему (змусить MySQL обробляти UTF-8 належним чином), але багато баз даних MySQL за замовчуванням встановлені на latin1, тому це не може зробити його правильним рішенням. Я змінив би діаграму за замовчуванням і таблиці таблиці на utf8mb4. Дійсно, ця відповідь досить неповна, тому я спростував її.
базовий6

-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/uk/charset-connection.html
DanielM

Також не повне рішення. Стовпці потрібні CHARACTER SET utf8. rootне виконає все важливе init_connect.
Рік Джеймс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.