Wie MySQL UTF-8 richtig handhabt

101

Eine der Antworten auf eine Frage, die ich gestern gestellt habe, schlug vor, dass ich sicherstellen sollte, dass meine Datenbank UTF-8-Zeichen korrekt verarbeiten kann. Wie kann ich das mit MySQL machen?

Ben
quelle
4
Ich hoffe wirklich, dass wir eine umfassende Antwort erhalten, die verschiedene MySQL-Versionen, Inkompatibilitäten usw. abdeckt
Edward Z. Yang
1
@ EdwardZ.Yang - MySQL 4.1 eingeführt CHARACTER SETs; 5.1.24 mit der Zusammenstellung deutscher Scharfschützen (ß) durcheinander gebracht, die durch Hinzufügen einer weiteren Zusammenstellung in 5.1.62 korrigiert wurde (was die Sache wohl noch schlimmer macht); 5.5.3 füllte utf8 mit dem neuen Zeichensatz utf8mb4 aus.
Rick James
1
Diese Frage ist die gleiche wie diese .. Bitte schauen Sie sich das stackoverflow.com/questions/3513773/…
Nyein Aung
Es sei darauf hingewiesen, dass die meisten dieser Antworten einfach falsch sind. Nicht verwenden utf8. Es werden nur bis zu 3-Byte-Zeichen unterstützt. Der richtige Zeichensatz, den Sie in MySQL verwenden sollten, ist utf8mb4.
Brendan Byrd

Antworten:

87

Aktualisieren:

Kurze Antwort - Sie sollten fast immer den utf8mb4Zeichensatz und die utf8mb4_unicode_ciSortierung verwenden.

So ändern Sie die Datenbank:

ALTER DATABASE dbname CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Sehen:

Ursprüngliche Antwort:

MySQL 4.1 und höher hat einen Standardzeichensatz von UTF-8. Sie können dies in Ihrer my.cnfDatei überprüfen. Denken Sie daran, sowohl Client als auch Server ( default-character-setund character-set-server) festzulegen .

Wenn Sie bereits Daten haben, die Sie in UTF-8 konvertieren möchten, sichern Sie Ihre Datenbank und importieren Sie sie als UTF-8 zurück. Stellen Sie dabei Folgendes sicher:

  • Verwenden SET NAMES utf8Sie diese Option, bevor Sie sie abfragen / in die Datenbank einfügen
  • Verwenden Sie diese DEFAULT CHARSET=utf8Option, wenn Sie neue Tabellen erstellen
  • Zu diesem Zeitpunkt sollten sich Ihr MySQL-Client und -Server in UTF-8 befinden (siehe my.cnf). Denken Sie daran, dass alle von Ihnen verwendeten Sprachen (z. B. PHP) ebenfalls UTF-8 sein müssen. Einige Versionen von PHP verwenden ihre eigene MySQL-Client-Bibliothek, die möglicherweise nicht UTF-8-fähig ist.

Wenn Sie vorhandene Daten migrieren möchten, denken Sie daran, zuerst zu sichern! Viele seltsame Datenverluste können auftreten, wenn die Dinge nicht wie geplant verlaufen!

Einige Ressourcen:

Owen
quelle
29
Nach meinem Verständnis utf8bezieht sich MySQL in MySQL nur auf eine kleine Teilmenge des vollständigen Unicode. Sie sollten utf8mb4stattdessen verwenden, um die volle Unterstützung zu erzwingen. Siehe mathiasbynens.be/notes/mysql-utf8mb4 "Lange Zeit habe ich den utf8-Zeichensatz von MySQL für Datenbanken, Tabellen und Spalten verwendet, vorausgesetzt, er ist der oben beschriebenen UTF-8-Codierung zugeordnet."
Aaron McDaid
7
MySQL hatte noch nie einen Standardzeichensatz von UTF-8. 4.1 und 5.x bis zum neuesten 5.7 verwenden alle latin1und latin1_swedish_cifür den Standardzeichensatz und die Standardkollatierung. Eine Bestätigung finden Sie auf der Seite "Server-Zeichensatz und Sortierung" im MySQL-Handbuch: dev.mysql.com/doc/refman/5.1/en/charset-server.html
Animism
2
@TimTisdall Sie müssen sich keine Sorgen machen utf8mb4, wenn der meiste Text ASCII ist. Obwohl charZeichenfolgen vorbelegt sind, sind varcharZeichenfolgen nicht zugeordnet - siehe die letzten Zeilen auf dieser Dokumentationsseite . Beispielsweise char(10)werden unter utf8mb4 pessimistisch 40 Bytes reserviert, es varchar(10)werden jedoch Bytes entsprechend der Codierung mit variabler Länge zugewiesen.
Kevin A. Naudé
1
@ Kevin Ich denke du hast das falsch verstanden. Ich denke, die maximale Zeilenlänge beträgt 64k. Sie können ein utf8mb4-Feld nur zu einem Viertel davon erstellen, da es diesen Speicherplatz reservieren musste. Selbst wenn es sich um ASCII handelt, können Sie nur 16.000 Zeichen einfügen.
Tim Tisdall
1
@ TimTisdall Oh, du sprichst von Obergrenzen. Ja, die sind niedriger. Glücklicherweise werden aktuelle Versionen von MySQL automatisch von varchar(n)auf den textDatentyp aktualisiert , wenn Sie versuchen, ein varchar(n)Feld so zu ändern , dass es größer als die zulässige Bytegröße ist (während Sie eine Warnung ausgeben). Ein Index hat auch eine untere Obergrenze im ungünstigsten Fall, was andere Probleme aufwerfen kann.
Kevin A. Naudé
43

Um dies "dauerhaft" zu machen, in my.cnf:

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

Um dies zu überprüfen, gehen Sie zum Client und zeigen Sie einige Variablen an:

SHOW VARIABLES LIKE 'character_set%';

Stellen Sie sicher , dass sie alle sind utf8, außer ..._filesystem, was sein sollte binaryund ..._dirwas irgendwo in der MySQL-Installation zeigt.

Javier
quelle
In meinem Fall hat es nicht funktioniert, aber ich habe trotzdem die Datei my.cf in / etc mit dem angegebenen Inhalt erstellt. Ich benutztecreate table my_name(field_name varchar(25) character set utf8);
Marek Bar
Die "SHOW VARIABLES LIKE 'character_set%';" Befehl enthüllte mir das Problem mit meiner Verbindung. Vielen Dank!
Javsmo
1
Das ist nicht richtig. Was MySQL aufruft, utf8ist nicht "voll" UTF-8.
TWR Cole
31

MySQL 4.1 und höher verfügt über einen Standardzeichensatz, den es aufruft utf8, der jedoch nur eine Teilmenge von UTF-8 ist (erlaubt nur Drei-Byte-Zeichen und weniger).

Verwenden Sie utf8mb4als Zeichensatz, wenn Sie "volles" UTF-8 möchten.

TWR Cole
quelle
5
Stimmen Sie definitiv zu, dies ist die einzig richtige Antwort. utf8enthält keine Zeichen wie Emoticons. utf8mb4tut. Überprüfen Sie dies für weitere Informationen zum Aktualisieren: mathiasbynens.be/notes/mysql-utf8mb4
jibai31
@Basti - Meistens korrekt (latin1 war bis vor kurzem die Standardeinstellung) und nicht vollständig (behandelt nicht das korrekte Einfügen / Auswählen von utf8-codierten Daten oder das Anzeigen in HTML).
Rick James
Hochachtungsvoll, @RickJames, sagte Basti "bisher" - ich kann mich nicht erinnern, Ihre Antwort gesehen zu haben, als ich dies gepostet habe.
TWR Cole
Leider gibt es ungefähr 5 deutlich unterschiedliche Symptome von utf8-Problemen und ungefähr 4 Dinge, die Programmierer falsch machen, um Probleme zu verursachen. Die meisten Antworten weisen nur auf eine Sache hin, die möglicherweise behoben werden muss. Die ursprüngliche Frage war weit gefasst, daher brauchte die Antwort alle 4. Vielleicht war Basti mit einem Symptom vertraut, für das Ihr einziger Aspekt die Lösung war.
Rick James
8
Nebenbei möchte ich einen Moment innehalten und dem MySQL-Team einen wirklich guten, harten Blick geben. o_o WTF habt ihr gedacht? Ist Ihnen klar, wie viel Verwirrung Sie durch das Erstellen einer Codepage in Ihrem Programm mit dem Namen "utf8" verursacht haben, die eigentlich nicht UTF-8 ist? Verdammte Arschlöcher. </ rant>
TWR Cole
19

Die kurze Antwort: An utf8mb44 Stellen verwenden:

  • Die Bytes in Ihrem Client sind utf8, nicht latin1 / cp1251 / etc.
  • SET NAMES utf8mb4 oder etwas Äquivalentes, wenn die Verbindung des Clients zu MySQL hergestellt wird
  • CHARACTER SET utf8mb4 auf allen Tabellen / Spalten - mit Ausnahme von Spalten, die ausschließlich ascii / hex / country_code / zip_code / etc.
  • <meta charset charset=UTF-8>wenn Sie in HTML ausgeben. (Ja, die Schreibweise ist hier anders.)

Weitere Infos ;
UTF8 den ganzen Weg

Die obigen Links enthalten die "detaillierte kanonische Antwort ist erforderlich, um alle Bedenken auszuräumen". - In diesem Forum ist der Platz begrenzt.

Bearbeiten

Neben CHARACTER SET utf8mb4"allen" Charakteren der Welt COLLATION utf8mb4_unicode_520_ciist wohl die "beste Allround" -Kollation zu verwenden. (Es gibt auch türkische, spanische usw. Kollatierungen für diejenigen, die die Nuancen in diesen Sprachen wollen.)

Rick James
quelle
Mein neuer Link zum Debuggen von utf8-Problemen aus der Ausgabe, die Sie erhalten.
Rick James
Warum unicode_520_ci nicht das Beste ist: stackoverflow.com/a/49982378/62202
Louis
@ Louis - Und wie ich angedeutet habe, sind spanische und türkische (sowie polnische) Benutzer möglicherweise nicht glücklich. "Bester Allrounder" schadet allen. MySQL 8.0 hat eine noch neuere "beste" Sortierung: utf8mb4_0900_ai_ci . Leider wieder L = Ł.
Rick James
4

Der Zeichensatz ist eine Eigenschaft der Datenbank (Standard) und der Tabelle. Sie können einen Blick darauf werfen (MySQL-Befehle):

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

Mit anderen Worten; Es ist ganz einfach, Ihren Datenbankzeichensatz zu überprüfen oder zu ändern:

ALTER TABLE `foo`.`bar` CHARACTER SET utf8;
Extraneon
quelle
1
Das ist nicht richtig. Was MySQL aufruft, utf8ist nicht "voll" UTF-8.
TWR Cole
2

Ich folgte Javiers Lösung, fügte aber in my.cnf einige andere Zeilen hinzu:

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

Ich habe diese Idee hier gefunden: http://dev.mysql.com/doc/refman/5.0/en/charset-server.html im ersten / einzigen Benutzerkommentar am Ende der Seite. Er erwähnt, dass das Überspringen des Zeichensatz-Client-Handshakes eine gewisse Bedeutung hat.

Vlad Balan
quelle
Diese ungeliebte Antwort ohne Stimmen war das einzige, was mir geholfen hat! Also bekommt es meine Stimme, das ist verdammt sicher. skip-character-set-client-handshakewar der Schlüssel.
Marcus
0

Diese Tipps zu MySQL und UTF-8 können hilfreich sein. Leider stellen sie keine vollständige Lösung dar, sondern nur gängige Fallstricke.

Edward Z. Yang
quelle
0

Stellen Sie ein database collation, dass es UTF-8 dann table collationauf den Datenbankstandard angewendet wird.

Gaurav Lad
quelle
-1

Ihre Antwort ist, dass Sie über MySQL-Einstellungen konfigurieren können. In Meine Antwort ist möglicherweise etwas aus dem Zusammenhang geraten, aber dies ist auch eine Hilfe für Sie.
wie man konfiguriert Character SetundCollation .

Für Anwendungen, die Daten mit dem Standard-MySQL-Zeichensatz und collation ( latin1, latin1_swedish_ci) speichern , sollte keine spezielle Konfiguration erforderlich sein. Wenn Anwendungen eine Datenspeicherung mit einem anderen Zeichensatz oder einer anderen Sortierung erfordern, können Sie Zeichensatzinformationen auf verschiedene Arten konfigurieren:

  • Geben Sie die Zeicheneinstellungen pro Datenbank an. Für Anwendungen, die eine Datenbank verwenden, ist beispielsweise möglicherweise erforderlich utf8, während für Anwendungen, die eine andere Datenbank verwenden, möglicherweise sjis erforderlich sind.
  • Geben Sie die Zeicheneinstellungen beim Serverstart an. Dies führt dazu, dass der Server die angegebenen Einstellungen für alle Anwendungen verwendet, die keine anderen Vorkehrungen treffen.
  • Geben Sie die Zeicheneinstellungen zur Konfigurationszeit an , wenn Sie MySQL aus dem Quellcode erstellen. Dies führt dazu, dass der Server die angegebenen Einstellungen für alle Anwendungen verwendet, ohne sie beim Serverstart angeben zu müssen.

In den hier gezeigten Beispielen für Ihre Frage zum Festlegen des utf8-Zeichensatzes wird hier auch die Kollatierung für hilfreichere ( utf8_general_ciKollatierung`) festgelegt.

Geben Sie die Zeicheneinstellungen pro Datenbank an

  CREATE DATABASE new_db
  DEFAULT CHARACTER SET utf8
  DEFAULT COLLATE utf8_general_ci;

Geben Sie die Zeicheneinstellungen beim Serverstart an

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

Geben Sie die Zeicheneinstellungen zur MySQL-Konfigurationszeit an

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

Verwenden Sie die folgenden Anweisungen, um die Werte der Zeichensatz- und Sortiersystemvariablen anzuzeigen, die für Ihre Verbindung gelten:

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

Dies mag eine lange Antwort sein, aber es gibt alle Möglichkeiten, die Sie verwenden können. Hoffentlich ist meine Antwort hilfreich für Sie. Weitere Informationen finden Sie unter http://dev.mysql.com/doc/refman/5.7/en/charset-applications.html

Vipin Jain
quelle
-2

SET NAMES UTF8

Das ist der Trick

Claudio
quelle
2
Während die Verwendung von SET NAMES UTF8(oder UTF8mb4) korrekt ist, erklären Sie nicht, was es tut (Zeichensatz, der für diese Verbindung verwendet wird). "Dies macht den Trick" klingt so, als würde es das Problem lösen (MySQL sollte UTF-8 richtig handhaben), aber viele MySQL-Datenbanken sind standardmäßig auf latin1 eingestellt, sodass dies keine richtige Lösung wäre. Ich würde den Standardzeichensatz und die Tabellenzeichensätze in utf8mb4 ändern. Wirklich, diese Antwort ist ziemlich unvollständig, also habe ich sie abgelehnt.
basic6
-2

DATENBANKVERBINDUNG ZU 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
quelle
-3

Stellen Sie Ihre Datenbankverbindung auf UTF8 ein:

  if($handle = @mysql_connect(DB_HOST, DB_USER, DB_PASS)){          
         //set to utf8 encoding
         mysql_set_charset('utf8',$handle);
  }
Flosse
quelle
Verwenden Sie beim Ausführen von PHP nicht die veraltete mysql_*Schnittstelle. Wechseln Sie zu mysqli_*oder PDO.
Rick James
-3

Konnte eine Lösung finden. Führen Sie die folgenden Schritte aus, wie unter http://technoguider.com/2015/05/utf8-set-up-in-mysql/ angegeben.

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
quelle
Die letzten beiden Zeilen sind redundant, da die erste bereits folgende enthält: dev.mysql.com/doc/refman/5.0/de/charset-connection.html
DanielM
Auch keine Komplettlösung. Die Spalten brauchen CHARACTER SET utf8. rootwird nicht das alles wichtige ausführen init_connect.
Rick James