Jak sprawić, by MySQL poprawnie obsługiwał UTF-8

102

Jedna z odpowiedzi na pytanie, które zadałem wczoraj, sugerowała, że ​​powinienem upewnić się, że moja baza danych poprawnie obsługuje znaki UTF-8. Jak mogę to zrobić z MySQL?

Ben
źródło
4
Naprawdę mam nadzieję, że otrzymamy wyczerpującą odpowiedź, obejmującą różne wersje MySQL, niezgodności itp.
Edward Z. Yang
1
@ EdwardZ.Yang - wprowadzono MySQL 4.1 CHARACTER SETs; 5.1.24 zepsuło zestawienie niemieckich ostrych-s (ß), które zostało skorygowane przez dodanie innego zestawienia w 5.1.62 (prawdopodobnie pogorszyło sytuację); 5.5.3 wypełnił utf8 nowym zestawem znaków utf8mb4.
Rick James
1
To pytanie jest identyczne z tym. Proszę spojrzeć na to stackoverflow.com/questions/3513773/ ...
Nyein Aung
Warto zauważyć, że większość z tych odpowiedzi jest po prostu błędna. Nie używać utf8. Obsługuje tylko znaki o długości do 3 bajtów. Prawidłowy zestaw znaków, którego powinieneś używać w MySQL, to utf8mb4.
Brendan Byrd

Odpowiedzi:

89

Aktualizacja:

Krótka odpowiedź - Prawie zawsze powinieneś używać utf8mb4zestawu znaków i utf8mb4_unicode_cisortowania.

Aby zmienić bazę danych:

ALTER DATABASE dbname CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Widzieć:

Oryginalna odpowiedź:

MySQL 4.1 i nowsze wersje mają domyślny zestaw znaków UTF-8. Możesz to sprawdzić w swoim my.cnfpliku, pamiętaj, aby ustawić zarówno klienta, jak i serwer ( default-character-seti character-set-server).

Jeśli masz istniejące dane, które chcesz przekonwertować na UTF-8, zrzuć bazę danych i zaimportuj ją z powrotem jako UTF-8, upewniając się, że:

  • użyj SET NAMES utf8przed zapytaniem / wstawieniem do bazy danych
  • używać DEFAULT CHARSET=utf8podczas tworzenia nowych tabel
  • w tym momencie twój klient i serwer MySQL powinien być w UTF-8 (zobacz my.cnf). pamiętaj, że wszystkie używane języki (takie jak PHP) również muszą być w formacie UTF-8. Niektóre wersje PHP będą używać własnej biblioteki klienta MySQL, która może nie obsługiwać UTF-8.

Jeśli chcesz przenieść istniejące dane, pamiętaj, aby najpierw wykonać kopię zapasową! Wiele dziwnych fragmentów danych może się zdarzyć, gdy sprawy nie idą zgodnie z planem!

Niektóre zasoby:

piekarnik
źródło
29
Rozumiem, że utf8w MySQL odnosi się tylko do niewielkiego podzbioru pełnego Unicode. Zamiast tego należy użyć, utf8mb4aby wymusić pełne wsparcie. Zobacz mathiasbynens.be/notes/mysql-utf8mb4 "Przez długi czas używałem zestawu znaków utf8 MySQL dla baz danych, tabel i kolumn, zakładając , że jest on odwzorowany na kodowanie UTF-8 opisane powyżej."
Aaron McDaid
7
MySQL nigdy nie miał domyślnego zestawu znaków UTF-8. 4.1 i 5.x do najnowszej wersji 5.7 wszystkie używają latin1i latin1_swedish_cidla domyślnego zestawu znaków i sortowania. Patrz „Serwer zestaw znaków i sortowaniem” stronę w podręczniku MySQL dla potwierdzenia: dev.mysql.com/doc/refman/5.1/en/charset-server.html
animizm
2
@TimTisdall Nie musisz martwić się o utf8mb4dodatkowe miejsce, gdy większość tekstu to ASCII. Chociaż charłańcuchy są wstępnie przydzielone, varcharłańcuchy nie są - zobacz kilka ostatnich wierszy na tej stronie dokumentacji . Na przykład, char(10)będzie pesymistycznie zarezerwował 40 bajtów pod utf8mb4, ale varchar(10)przydzieli bajty zgodnie z kodowaniem o zmiennej długości.
Kevin A. Naudé
1
@Kevin Myślę, że źle to przeczytałeś. Myślę, że maksymalna długość wiersza to 64 kB. Możesz zrobić tylko 1/4 pola utf8mb4, ponieważ musiało zarezerwować taką ilość miejsca. Więc nawet jeśli jest to ASCII, możesz wstawić tylko 16k znaków.
Tim Tisdall
1
@TimTisdall Och, mówisz o górnych granicach. Tak, te są niższe. Na szczęście, obecne wersje MySQL automatycznie uaktualnić varchar(n)do texttypu danych, jeśli próbować zmieniać się varchar(n)pole do większej niż możliwym rozmiarze bajtów (wydając ostrzeżenie). Indeks będzie miał również dolną górną granicę najgorszego przypadku, co może powodować inne problemy.
Kevin A. Naudé
44

Aby to było „trwałe”, w my.cnf:

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

Aby to sprawdzić, przejdź do klienta i pokaż kilka zmiennych:

SHOW VARIABLES LIKE 'character_set%';

Sprawdź, czy są one wszystkie utf8, z wyjątkiem tego ..._filesystem, co powinno być binaryi ..._dir, co wskazuje gdzieś w instalacji MySQL.

Javier
źródło
W moim przypadku to nie zadziałało, ale i tak utworzyłem plik my.cf w / etc z podaną zawartością. Skorzystałemcreate table my_name(field_name varchar(25) character set utf8);
Marek Bar
„POKAŻ ZMIENNE PODOBNE '' zestaw_znaków% ';" polecenie ujawniło mi problem z połączeniem. Dzięki!
javsmo
1
To nie jest poprawne. To, co MySQL nazywa, utf8nie jest „pełnym” UTF-8.
TWR Cole
32

MySQL 4.1 i nowsze wersje mają domyślny zestaw znaków, który wywołuje, utf8ale który w rzeczywistości jest tylko podzbiorem UTF-8 (dopuszcza tylko znaki trzy-bajtowe i mniejsze).

Użyj utf8mb4jako swojego zestawu znaków, jeśli chcesz mieć „pełny” UTF-8.

TWR Cole
źródło
5
Zdecydowanie się zgadzam, to jedyna poprawna odpowiedź. utf8nie zawiera znaków, takich jak emotikony. utf8mb4robi. Sprawdź to, aby uzyskać więcej informacji na temat aktualizacji: mathiasbynens.be/notes/mysql-utf8mb4
jibai
@Basti - w większości poprawne (latin1 było domyślne do niedawna) i niekompletne (nie omawia prawidłowego wstawiania / wybierania danych zakodowanych w utf8 ani wyświetlania w html).
Rick James
Z całym szacunkiem, @RickJames, Basti powiedział „jak dotąd” - nie pamiętam Twojej odpowiedzi, kiedy to opublikowałem.
TWR Cole
Niestety, istnieje około 5 wyraźnie różnych objawów problemów z utf8 i około 4 rzeczy, które programiści robią źle, aby spowodować problemy. Większość odpowiedzi wskazuje tylko jedną rzecz, która może wymagać naprawy. Pierwotne pytanie było szerokie, więc odpowiedź wymagała wszystkich 4. Być może Basti znał jeden objaw, dla którego jeden aspekt był rozwiązaniem.
Rick James,
8
Na marginesie chciałbym zatrzymać się na chwilę i rzucić zespołowi MySQL naprawdę dobre, twarde spojrzenie. o_o WTF myśleliście? Czy zdajesz sobie sprawę, jak wiele zamieszania zasiałeś, tworząc w swoim programie stronę kodową o nazwie „utf8”, która nie jest w rzeczywistości UTF-8? Cholerne dupki. </rant>
TWR Cole
20

Krótka odpowiedź: używaj utf8mb4w 4 miejscach:

  • Bajty w twoim kliencie to utf8, a nie latin1 / cp1251 / etc.
  • SET NAMES utf8mb4 lub coś równoważnego podczas nawiązywania połączenia klienta z MySQL
  • CHARACTER SET utf8mb4 we wszystkich tabelach / kolumnach - z wyjątkiem kolumn, które są ściśle ascii / hex / country_code / zip_code / etc.
  • <meta charset charset=UTF-8>jeśli drukujesz do HTML. (Tak, pisownia jest inna).

Więcej informacji ;
UTF8 w całości

Powyższe linki zapewniają „szczegółową odpowiedź kanoniczną jest wymagana, aby odpowiedzieć na wszystkie wątpliwości”. - Na tym forum obowiązuje limit miejsca.

Edytować

Oprócz tego, że CHARACTER SET utf8mb4zawiera „wszystkie” znaki świata, COLLATION utf8mb4_unicode_520_cijest to prawdopodobnie „najlepsze wszechstronne” zestawienie do użycia. (Istnieją również zestawienia języka tureckiego, hiszpańskiego itp. Dla tych, którzy chcą niuansów w tych językach).

Rick James
źródło
Mój nowy link o tym, jak debugować problemy z utf8 na podstawie otrzymanych wyników.
Rick James,
Dlaczego unicode_520_ci nie jest najlepszy pod każdym względem: stackoverflow.com/a/49982378/62202
Louis
@Louis - I jak zasugerowałem hiszpańscy i tureccy (a także polscy) użytkownicy mogą nie być zadowoleni. „Najlepsze pod każdym względem” zwykle ranią każdego. MySQL 8.0 ma jeszcze nowsze „najlepsze” sortowanie: utf8mb4_0900_ai_ci . Niestety, znowu L = Ł.
Rick James
4

Zestaw znaków jest właściwością bazy danych (domyślnie) i tabeli. Możesz rzucić okiem (polecenia 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

Innymi słowy; całkiem łatwo jest sprawdzić kodowanie bazy danych lub go zmienić:

ALTER TABLE `foo`.`bar` CHARACTER SET utf8;
extraneon
źródło
1
To nie jest poprawne. To, co MySQL nazywa, utf8nie jest „pełnym” UTF-8.
TWR Cole
2

Postępowałem zgodnie z rozwiązaniem Javiera, ale dodałem kilka różnych wierszy w my.cnf:

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

Znalazłem ten pomysł tutaj: http://dev.mysql.com/doc/refman/5.0/en/charset-server.html w pierwszym / jedynym komentarzu użytkownika na dole strony. Wspomina, że uścisk dłoni z pominięciem zestawu znaków i klienta ma pewne znaczenie.

Vlad Balan
źródło
Ta niekochana odpowiedź bez głosów była jedyną rzeczą, która mi pomogła! Więc otrzymuję mój głos, to na pewno. skip-character-set-client-handshakebył klucz.
Marcus
0

Określ database collation, aby UTF-8 następnie zastosować table collationdo domyślnej bazy danych.

Gaurav Lad
źródło
-1

Twoja odpowiedź brzmi: możesz skonfigurować ustawienia MySql. W My Answer może być coś wyrwanego z kontekstu, ale to również jest pomoc dla ciebie.
jak skonfigurować Character SetiCollation .

W przypadku aplikacji, które przechowują dane przy użyciu domyślnego zestawu znaków MySQL i funkcji collation ( latin1, latin1_swedish_ci), nie jest wymagana żadna specjalna konfiguracja. Jeśli aplikacje wymagają przechowywania danych przy użyciu innego zestawu znaków lub sortowania, możesz skonfigurować informacje o zestawie znaków na kilka sposobów:

  • Określ ustawienia znaków dla każdej bazy danych. Na przykład aplikacje korzystające z jednej bazy danych mogą wymagać utf8, podczas gdy aplikacje korzystające z innej bazy danych mogą wymagać sjis.
  • Określ ustawienia znaków podczas uruchamiania serwera. Powoduje to, że serwer używa podanych ustawień dla wszystkich aplikacji, które nie dokonują innych ustaleń.
  • Określ ustawienia znaków w czasie konfiguracji , jeśli budujesz MySQL ze źródła. Powoduje to, że serwer używa podanych ustawień dla wszystkich aplikacji, bez konieczności określania ich podczas uruchamiania serwera.

Przykłady pokazane tutaj dla twojego pytania, aby ustawić zestaw znaków utf8, tutaj również ustaw sortowanie dla bardziej pomocnego ( utf8_general_cicollation`).

Określ ustawienia znaków dla każdej bazy danych

  CREATE DATABASE new_db
  DEFAULT CHARACTER SET utf8
  DEFAULT COLLATE utf8_general_ci;

Określ ustawienia znaków podczas uruchamiania serwera

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

Określ ustawienia znaków w czasie konfiguracji MySQL

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

Aby zobaczyć wartości zestawu znaków i zmiennych systemowych sortowania, które mają zastosowanie do Twojego połączenia, użyj następujących instrukcji:

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

To może być długa odpowiedź, ale jest cała droga, której możesz użyć. Mam nadzieję, że moja odpowiedź jest dla ciebie pomocna. aby uzyskać więcej informacji http://dev.mysql.com/doc/refman/5.7/en/charset-applications.html

Vipin Jain
źródło
-2

SET NAMES UTF8

To załatwia sprawę

Claudio
źródło
2
Chociaż użycie SET NAMES UTF8(lub UTF8mb4) jest poprawne, nie wyjaśniasz, co robi (zestaw znaków używany do tego połączenia). „To załatwia sprawę” brzmi tak, jakby rozwiązało problem (sprawi, że MySQL poprawnie obsłuży UTF-8), ale wiele baz danych MySQL jest domyślnie ustawionych na latin1, więc nie byłoby to właściwe rozwiązanie. Chciałbym zmienić domyślny zestaw znaków i kodowania znaków, stół do utf8mb4. Naprawdę, ta odpowiedź jest raczej niekompletna, więc ją odrzuciłem.
podstawowy 6
-2

PODŁĄCZENIE BAZY DANYCH DO 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());
sunil subramanya
źródło
-3

Ustaw połączenie bazy danych na UTF8:

  if($handle = @mysql_connect(DB_HOST, DB_USER, DB_PASS)){          
         //set to utf8 encoding
         mysql_set_charset('utf8',$handle);
  }
płetwa
źródło
Jeśli używasz PHP, nie używaj przestarzałego mysql_*interfejsu. Przełącz na mysqli_*lub PDO.
Rick James,
-3

Udało mi się znaleźć rozwiązanie. Uruchomiono następujące, jak określono na 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;
Nishant
źródło
Ostatnie dwie linie są zbędne, ponieważ pierwsza zawiera już te: dev.mysql.com/doc/refman/5.0/en/charset-connection.html
DanielM
Również nie jest to kompletne rozwiązanie. Kolumny potrzebują CHARACTER SET utf8. rootnie wykona najważniejszego init_connect.
Rick James,