Mysql
 sql >> Base de données >  >> RDS >> Mysql

Problème avec les caractères UTF-8 ; ce que je vois n'est pas ce que j'ai stocké

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 avec SHOW 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.

UTF- 8 jusqu'au bout

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 , ou 7x
  • 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 le INSERT et le SELECT 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 le SELECT 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. (Utilisez SHOW 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 et SELECTing 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