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?


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:


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.


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.


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.)


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;

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.


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

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


-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


-2

SET NAMES UTF8

Das ist der Trick


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());

-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);
  }

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;

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.