Comment faire en sorte que MySQL gère correctement UTF-8

102

L'une des réponses à une question que j'ai posée hier m'a suggéré de m'assurer que ma base de données peut gérer correctement les caractères UTF-8. Comment puis-je faire cela avec MySQL?

Ben
la source
4
J'espère vraiment que nous aurons une réponse complète, couvrant différentes versions de MySQL, les incompatibilités, etc.
Edward Z. Yang
1
@ EdwardZ.Yang - MySQL 4.1 introduit CHARACTER SETs; 5.1.24 a gâché la collation de l'allemand sharp-s (ß), qui a été corrigée en ajoutant une autre collation dans 5.1.62 (sans doute aggravant les choses); 5.5.3 a rempli utf8 avec le nouveau jeu de caractères utf8mb4.
Rick James
1
Cette question est tout à fait la même que celle-ci .. S'il vous plaît regarder que stackoverflow.com/questions/3513773/…
Nyein Aung
Il convient de souligner que la plupart de ces réponses sont tout simplement fausses. Ne l'utilisez pas utf8. Il ne prend en charge que les caractères jusqu'à 3 octets. Le jeu de caractères correct que vous devez utiliser dans MySQL est utf8mb4.
Brendan Byrd

Réponses:

89

Mettre à jour:

Réponse courte - Vous devriez presque toujours utiliser le utf8mb4jeu de caractères et la utf8mb4_unicode_cicollation.

Pour modifier la base de données:

ALTER DATABASE dbname CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Voir:

Réponse originale:

MySQL 4.1 et supérieur a un jeu de caractères par défaut de UTF-8. Vous pouvez vérifier cela dans votre my.cnffichier, n'oubliez pas de définir à la fois client et serveur ( default-character-setet character-set-server).

Si vous avez des données existantes que vous souhaitez convertir en UTF-8, videz votre base de données et réimportez-la au format UTF-8 en vous assurant:

  • utiliser SET NAMES utf8avant d'interroger / insérer dans la base de données
  • utiliser DEFAULT CHARSET=utf8lors de la création de nouvelles tables
  • à ce stade, votre client et serveur MySQL doivent être en UTF-8 (voir my.cnf). rappelez-vous que toutes les langues que vous utilisez (comme PHP) doivent également être UTF-8. Certaines versions de PHP utiliseront leur propre bibliothèque client MySQL, qui peut ne pas être compatible UTF-8.

Si vous souhaitez migrer les données existantes, n'oubliez pas de sauvegarder d'abord! Beaucoup de découpages étranges de données peuvent se produire lorsque les choses ne se passent pas comme prévu!

Quelques ressources:

Owen
la source
29
Ma compréhension est que utf8dans MySQL ne fait référence qu'à un petit sous-ensemble d'Unicode complet. Vous devriez utiliser à la utf8mb4place pour forcer le support complet. Voir mathiasbynens.be/notes/mysql-utf8mb4 "Pendant longtemps, j'utilisais le jeu de caractères utf8 de MySQL pour les bases de données, les tables et les colonnes, en supposant qu'il était mappé au codage UTF-8 décrit ci-dessus."
Aaron McDaid
7
MySQL n'a jamais eu de jeu de caractères par défaut UTF-8. 4.1 et 5.x jusqu'à la dernière version 5.7 toutes utilisent latin1et latin1_swedish_cipour le jeu de caractères et le classement par défaut. Consultez la page "Jeu de caractères du serveur et classement" dans le manuel MySQL pour confirmation: dev.mysql.com/doc/refman/5.1/en/charset-server.html
Animism
2
@TimTisdall Vous n'avez pas à vous soucier utf8mb4de la capacité de stockage supplémentaire lorsque la plupart du texte est ASCII. Bien que les charchaînes soient préallouées, les varcharchaînes ne le sont pas - voir les dernières lignes de cette page de documentation . Par exemple, char(10)sera réservé de manière pessimiste 40 octets sous utf8mb4, mais varchar(10)allouera des octets conformément au codage de longueur variable.
Kevin A. Naudé
1
@Kevin Je pense que vous avez mal interprété cela. Je pense que la longueur maximale des lignes est de 64k. Vous ne pouvez créer un champ utf8mb4 que 1/4 car il devait réserver cette quantité d'espace. Ainsi, même si c'est ASCII, vous ne pouvez insérer que 16k caractères.
Tim Tisdall
1
@TimTisdall Oh, vous parlez des limites supérieures. Oui, ceux-ci sont inférieurs. Heureusement, les versions actuelles de MySQL met automatiquement à partir varchar(n)du texttype de données si vous essayez de modifier un varchar(n)champ plus grand que la taille d'octets possible (tout en émettant un avertissement). Un index aura également une limite supérieure inférieure dans le pire des cas, ce qui peut présenter d'autres problèmes.
Kevin A. Naudé
44

Pour rendre cela `` permanent '', en my.cnf:

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

Pour vérifier, accédez au client et affichez quelques variables:

SHOW VARIABLES LIKE 'character_set%';

Vérifiez qu'ils sont tous utf8, sauf ..._filesystem, qui devrait être binaryet ..._dir, qui pointe quelque part dans l'installation de MySQL.

Javier
la source
Cela n'a pas fonctionné dans mon cas, mais j'ai quand même créé le fichier my.cf dans / etc avec un contenu donné. J'ai utilisécreate table my_name(field_name varchar(25) character set utf8);
Marek Bar
"SHOW VARIABLES LIKE 'character_set%';" La commande m'a révélé le problème de ma connexion. Merci!
javsmo
1
Ce n'est pas correct. Ce que MySQL appelle utf8n'est pas UTF-8 "complet".
TWR Cole
32

MySQL 4.1 et supérieur a un jeu de caractères par défaut qu'il appelle utf8mais qui n'est en fait qu'un sous-ensemble d'UTF-8 (n'autorise que des caractères de trois octets et plus petits).

Utilisez-le utf8mb4comme jeu de caractères si vous voulez un UTF-8 "complet".

TWR Cole
la source
5
Tout à fait d'accord, c'est la seule bonne réponse. utf8n'inclut pas les caractères comme les émoticônes. utf8mb4Est-ce que. Vérifiez ceci pour plus d'informations sur la mise à jour: mathiasbynens.be/notes/mysql-utf8mb4
jibai31
@Basti - Plutôt correct (latin1 était la valeur par défaut jusqu'à tout récemment), et pas complet (ne traite pas correctement de l'insertion / sélection de données encodées en utf8, ni de l'affichage en html).
Rick James
Respectueusement, @RickJames, Basti a dit "jusqu'ici" - je ne me souviens pas avoir vu votre réponse quand j'ai posté ceci.
TWR Cole
Hélas, il y a environ 5 symptômes distincts de problèmes utf8 et environ 4 choses que les programmeurs font de mal pour causer des problèmes. La plupart des réponses ne signalent qu'une seule chose qui peut nécessiter une correction. La question initiale était large, donc la réponse nécessitait toutes les 4. Peut-être que Basti connaissait un symptôme pour lequel votre seul aspect était la solution.
Rick James
8
En passant, j'aimerais faire une pause et donner à l'équipe MySQL un très bon regard dur. o_o WTF pensiez-vous les gars? Vous rendez-vous compte de la confusion que vous avez semée en créant une page de codes dans votre programme appelée "utf8" qui n'est pas en fait UTF-8? Putain de connards. </rant>
TWR Cole
20

La réponse courte: à utiliser utf8mb4à 4 endroits:

  • Les octets de votre client sont utf8, pas latin1 / cp1251 / etc.
  • SET NAMES utf8mb4 ou quelque chose d'équivalent lors de l'établissement de la connexion du client à MySQL
  • CHARACTER SET utf8mb4 sur toutes les tables / colonnes - à l'exception des colonnes qui sont strictement ascii / hex / country_code / zip_code / etc.
  • <meta charset charset=UTF-8>si vous sortez au format HTML. (Oui, l'orthographe est différente ici.)

Plus d'infos ;
UTF8 jusqu'au bout

Les liens ci-dessus fournissent la "réponse canonique détaillée est nécessaire pour répondre à toutes les préoccupations". - Il y a une limite d'espace sur ce forum.

Éditer

En plus de CHARACTER SET utf8mb4contenir «tous» les personnages du monde, COLLATION utf8mb4_unicode_520_cion peut soutenir la meilleure collation «tout autour» à utiliser. (Il existe également des classements turc, espagnol, etc. pour ceux qui veulent les nuances dans ces langues.)

Rick James
la source
Mon nouveau lien sur la façon de déboguer les problèmes utf8 à partir de la sortie que vous obtenez.
Rick James
Pourquoi unicode_520_ci n'est pas le meilleur tout autour: stackoverflow.com/a/49982378/62202
Louis
@Louis - Et comme je l'ai laissé entendre, les utilisateurs espagnols et turcs (ainsi que polonais) peuvent ne pas être satisfaits. «Best all-around» a tendance à blesser tout le monde. MySQL 8.0 a une "meilleure" collation encore plus récente: utf8mb4_0900_ai_ci . Hélas, encore une fois L = £.
Rick James
4

Le jeu de caractères est une propriété de la base de données (par défaut) et de la table. Vous pouvez jeter un œil (commandes 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

En d'autres termes; il est assez facile de vérifier le jeu de caractères de votre base de données ou de le modifier:

ALTER TABLE `foo`.`bar` CHARACTER SET utf8;
extraneon
la source
1
Ce n'est pas correct. Ce que MySQL appelle utf8n'est pas UTF-8 "complet".
TWR Cole
2

J'ai suivi la solution de Javier, mais j'ai ajouté quelques lignes différentes dans my.cnf:

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

J'ai trouvé cette idée ici: http://dev.mysql.com/doc/refman/5.0/en/charset-server.html dans le premier / seul commentaire utilisateur en bas de page. Il mentionne que skip-character-set-client-handshake a une certaine importance.

Vlad Balan
la source
Cette réponse mal aimée et sans vote a été la seule chose qui m'a aidé! Donc, il obtient mon vote, c'est à coup sûr. skip-character-set-client-handshakeétait la clé.
Marcus
0

Ces conseils sur MySQL et UTF-8 peuvent être utiles. Malheureusement, ils ne constituent pas une solution complète, juste des pièges courants.

Edward Z. Yang
la source
0

Définissez votre database collationpour UTF-8 puis appliquer table collationà la base de données par défaut.

Gaurav Lad
la source
-1

Votre réponse est que vous pouvez configurer par MySql Settings. Dans ma réponse, il se peut que ce soit quelque chose qui sort de son contexte, mais c'est aussi une aide pour vous.
comment configurer Character SetetCollation .

Pour les applications qui stockent des données en utilisant le jeu de caractères MySQL par défaut et collation ( latin1, latin1_swedish_ci), aucune configuration spéciale ne devrait être nécessaire. Si les applications nécessitent un stockage de données à l'aide d'un jeu de caractères ou d'un classement différent, vous pouvez configurer les informations du jeu de caractères de plusieurs manières:

  • Spécifiez les paramètres de caractère par base de données. Par exemple, les applications qui utilisent une base de données peuvent nécessiterutf8 , tandis que les applications qui utilisent une autre base de données peuvent nécessiter sjis.
  • Spécifiez les paramètres de caractère au démarrage du serveur.Cela oblige le serveur à utiliser les paramètres donnés pour toutes les applications qui ne prennent pas d'autres dispositions.
  • Spécifiez les paramètres de caractères au moment de la configuration , si vous créez MySQL à partir de la source. Cela oblige le serveur à utiliser les paramètres donnés pour toutes les applications, sans avoir à les spécifier au démarrage du serveur.

Les exemples montrés ici pour votre question pour définir le jeu de caractères utf8, ici également définir le classement pour plus utile ( utf8_general_cicollation`).

Spécifiez les paramètres de caractère par base de données

  CREATE DATABASE new_db
  DEFAULT CHARACTER SET utf8
  DEFAULT COLLATE utf8_general_ci;

Spécifier les paramètres de caractère au démarrage du serveur

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

Spécifiez les paramètres de caractères au moment de la configuration de MySQL

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

Pour afficher les valeurs du jeu de caractères et des variables système de classement qui s'appliquent à votre connexion, utilisez ces instructions:

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

Cela peut être une longue réponse, mais il y a tous les moyens, vous pouvez utiliser. J'espère que ma réponse vous sera utile. pour plus d'informations http://dev.mysql.com/doc/refman/5.7/en/charset-applications.html

Vipin Jain
la source
-2

SET NAMES UTF8

Cela fait l'affaire

Claudio
la source
2
Si l'utilisation de SET NAMES UTF8(ou UTF8mb4) est correcte, vous n'expliquez pas ce qu'il fait (jeu de caractères utilisé pour cette connexion). "Cela fait l'affaire" semble résoudre le problème (faire en sorte que MySQL gère correctement UTF-8), mais de nombreuses bases de données MySQL sont réglées sur latin1 par défaut, donc cela ne ferait pas une bonne solution. Je changerais le jeu de caractères par défaut et les jeux de caractères de table en utf8mb4. Vraiment, cette réponse est plutôt incomplète, alors je l'ai déclinée.
base6
-2

CONNEXION DE LA BASE DE DONNÉES À L'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
la source
-3

Définissez votre connexion à la base de données sur UTF8:

  if($handle = @mysql_connect(DB_HOST, DB_USER, DB_PASS)){          
         //set to utf8 encoding
         mysql_set_charset('utf8',$handle);
  }
ailette
la source
Si vous utilisez PHP, n'utilisez pas l' mysql_*interface obsolète . Basculez vers mysqli_*ou PDO.
Rick James
-3

A pu trouver une solution. Ran the following comme spécifié à 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
la source
Les deux dernières lignes sont redondantes, puisque la première inclut déjà celles: dev.mysql.com/doc/refman/5.0/en/charset-connection.html
DanielM
Pas non plus une solution complète. Les colonnes ont besoin CHARACTER SET utf8. rootn'exécutera pas le plus important init_connect.
Rick James