Ce problème afflige les participants de ce site, et bien d'autres.
Vous avez listé les cinq principaux cas de CHARACTER SET
problèmes.
Meilleures pratiques
À l'avenir, il est préférable d'utiliser CHARACTER SET utf8mb4
et COLLATION utf8mb4_unicode_520_ci
. (Il existe une version plus récente du classement Unicode dans le pipeline.)
utf8mb4
est un sur-ensemble de utf8
en ce sens qu'il gère les codes utf8 à 4 octets, nécessaires à Emoji et à certains Chinois.
En dehors de MySQL, "UTF-8" fait référence à tous les encodages de taille, donc effectivement identique à utf8mb4
de MySQL , pas utf8
.
Je vais essayer d'utiliser ces orthographes et majuscules pour faire la distinction entre l'intérieur et l'extérieur de MySQL dans ce qui suit.
Aperçu de ce que vous devriez faire
- Réglez votre éditeur, etc. sur UTF-8.
- Les formulaires HTML doivent commencer par
<form accept-charset="UTF-8">
. - Encodez vos octets en UTF-8.
- Définissez UTF-8 comme encodage utilisé dans le client.
- Déclarer la colonne/table
CHARACTER SET utf8mb4
(Vérifier avecSHOW CREATE TABLE
.) <meta charset=UTF-8>
au début du HTML- Les routines stockées acquièrent le jeu de caractères/collation actuel. Ils peuvent avoir besoin d'être reconstruits.
Plus de détails sur les langages informatiques (et ses sections suivantes)
Tester les données
Visualisation des données avec un outil ou avec SELECT
ne peut pas faire confiance.Trop de ces clients, en particulier les navigateurs, essaient de compenser les encodages incorrects et vous montrent le texte correct même si la base de données est mutilée.Alors, choisissez une table et une colonne contenant du texte non anglais et faites
SELECT col, HEX(col) FROM tbl WHERE ...
Le HEX pour UTF-8 correctement stocké sera
- Pour un espace vide (dans n'importe quelle langue) :
20
- Pour l'anglais :
4x
,5x
,6x
, ou7x
- Pour la plupart des pays d'Europe occidentale, les lettres accentuées doivent être
Cxyy
- Cyrillique, hébreu et farsi/arabe :
Dxyy
- La majeure partie de l'Asie :
Exyyzz
- Emoji et quelques chinois :
F0yyzzww
- Plus de détails
Causes spécifiques et solutions aux problèmes observés
Tronqué texte (Se
pour Señor
):
- Les octets à stocker ne sont pas encodés en utf8mb4. Corrigez ça.
- Vérifiez également que la connexion pendant la lecture est UTF-8.
Diamants noirs avec des points d'interrogation (Se�or
pour Señor
); un de ces cas existe :
Cas 1 (les octets d'origine n'étaient pas UTF-8):
- Les octets à stocker ne sont pas encodés en utf8. Corrigez ça.
- La connexion (ou
SET NAMES
) pour leINSERT
et leSELECT
n'était pas utf8/utf8mb4. Corrigez ça. - Vérifiez également que la colonne dans la base de données est
CHARACTER SET utf8
(ou utf8mb4).
Cas 2 (les octets d'origine étaient UTF-8):
- La connexion (ou
SET NAMES
) pour leSELECT
n'était pas utf8/utf8mb4. Corrigez ça. - Vérifiez également que la colonne dans la base de données est
CHARACTER SET utf8
(ou utf8mb4).
Les losanges noirs n'apparaissent que lorsque le navigateur est défini sur <meta charset=UTF-8>
.
Points d'interrogation (les diamants réguliers, pas les diamants noirs) (Se?or
pour Señor
):
- Les octets à stocker ne sont pas encodés en utf8/utf8mb4. Corrigez ça.
- La colonne de la base de données n'est pas
CHARACTER SET utf8
(ou utf8mb4). Répare ça. (UtilisezSHOW CREATE TABLE
.) - Vérifiez également que la connexion pendant la lecture est UTF-8.
Mojibake (Señor
pour Señor
):(Cette discussion s'applique également au double codage , qui n'est pas forcément visible.)
- Les octets à stocker doivent être encodés en UTF-8. Corrigez ça.
- La connexion lors de l'
INSERTing
etSELECTing
le texte doit spécifier utf8 ou utf8mb4. Corrigez ça. - La colonne doit être déclarée
CHARACTER SET utf8
(ou utf8mb4). Corrigez ça. - HTML doit commencer par
<meta charset=UTF-8>
.
Si les données semblent correctes, mais ne sont pas triées correctement, soit vous avez choisi le mauvais classement, soit aucun classement ne correspond à vos besoins, soit vous avez un double encodage .
Double encodage peut être confirmé en faisant le SELECT .. HEX ..
décrit ci-dessus.
é should come back C3A9, but instead shows C383C2A9
The Emoji 👽 should come back F09F91BD, but comes back C3B0C5B8E28098C2BD
C'est-à-dire que l'hexagone est environ deux fois plus long qu'il ne devrait l'être. Cela est dû à la conversion de latin1 (ou autre) en utf8, puis au traitement de ces octets comme s'ils étaient latin1 et à la répétition de la conversion. Le tri (et la comparaison) ne fait pas fonctionner correctement car il s'agit, par exemple, de trier comme si la chaîne était Señor
.
Correction des données, si possible
Pour la troncature et Points d'interrogation , les données sont perdues.
Pour Mojibake / Double Encodage , ...
Pour les diamants noirs , ...
Les correctifs sont répertoriés ici. (5 correctifs différents pour 5 situations différentes ; choisissez avec soin) :http://mysql. rjweb.org/doc.php/charcoll#fixes_for_various_cases