sql >> Base de Datos >  >> RDS >> Mysql

Problemas con los caracteres UTF-8; lo que veo no es lo que almacené

Este problema afecta a los participantes de este sitio y a muchos otros.

Ha enumerado los cinco casos principales de CHARACTER SET problemas.

Prácticas recomendadas

De ahora en adelante, es mejor usar CHARACTER SET utf8mb4 y COLLATION utf8mb4_unicode_520_ci . (Hay una versión más reciente de la intercalación Unicode en preparación).

utf8mb4 es un superconjunto de utf8 ya que maneja códigos utf8 de 4 bytes, que son necesarios para Emoji y algunos chinos.

Fuera de MySQL, "UTF-8" se refiere a codificaciones de todos los tamaños, por lo tanto, es igual a utf8mb4 de MySQL. , no utf8 .

Trataré de usar esas ortografías y mayúsculas para distinguir MySQL interno y externo en lo siguiente.

Resumen de lo que debería hacer

  • Haga que su editor, etc. se establezca en UTF-8.
  • Los formularios HTML deben comenzar como <form accept-charset="UTF-8"> .
  • Codifique sus bytes como UTF-8.
  • Establezca UTF-8 como la codificación que se utiliza en el cliente.
  • Tener la columna/tabla declarada CHARACTER SET utf8mb4 (Consulte con SHOW CREATE TABLE .)
  • <meta charset=UTF-8> al principio de HTML
  • Las rutinas almacenadas adquieren el conjunto de caracteres/intercalación actual. Es posible que necesiten reconstrucción.

UTF- 8 hasta el final

Más detalles sobre lenguajes informáticos (y sus siguientes secciones)

Prueba los datos

Ver los datos con una herramienta o con SELECT no se puede confiar. Muchos de estos clientes, especialmente los navegadores, intentan compensar las codificaciones incorrectas y mostrarle el texto correcto incluso si la base de datos está alterada. Por lo tanto, elija una tabla y una columna que tenga algún texto que no esté en inglés y haga

SELECT col, HEX(col) FROM tbl WHERE ...

El HEX para UTF-8 almacenado correctamente será

  • Para un espacio en blanco (en cualquier idioma):20
  • Para inglés:4x , 5x , 6x , o 7x
  • Para la mayor parte de Europa occidental, las letras acentuadas deben ser Cxyy
  • Cirílico, hebreo y farsi/árabe:Dxyy
  • La mayor parte de Asia:Exyyzz
  • Emoji y algo de chino:F0yyzzww
  • Más detalles

Causas específicas y soluciones de los problemas observados

Truncado texto (Se para Se�or ):

  • Los bytes que se almacenarán no están codificados como utf8mb4. Soluciona esto.
  • Además, verifique que la conexión durante la lectura sea UTF-8.

Diamantes negros con signos de interrogación (Se�or para Se�or ); uno de estos casos existe:

Caso 1 (los bytes originales no UTF-8):

  • Los bytes que se almacenarán no están codificados como utf8. Soluciona esto.
  • La conexión (o SET NAMES ) para el INSERT y el SELECT no era utf8/utf8mb4. Soluciona esto.
  • Además, verifique que la columna en la base de datos sea CHARACTER SET utf8 (o utf8mb4).

Caso 2 (los bytes originales eran UTF-8):

  • La conexión (o SET NAMES ) para SELECT no era utf8/utf8mb4. Soluciona esto.
  • Además, verifique que la columna en la base de datos sea CHARACTER SET utf8 (o utf8mb4).

Los diamantes negros aparecen solo cuando el navegador está configurado en <meta charset=UTF-8> .

Signos de interrogación (normales, no diamantes negros) (Se�or para Se�or ):

  • Los bytes que se almacenarán no están codificados como utf8/utf8mb4. Soluciona esto.
  • La columna en la base de datos no es CHARACTER SET utf8 (o utf8mb4). Arregla esto. (Utilice SHOW CREATE TABLE .)
  • Además, verifique que la conexión durante la lectura sea UTF-8.

Mojibake (Se�or para Se�or ):(Esta discusión también se aplica a Codificación doble , que no es necesariamente visible).

  • Los bytes que se almacenarán deben estar codificados en UTF-8. Soluciona esto.
  • La conexión cuando INSERTing y SELECTing el texto debe especificar utf8 o utf8mb4. Soluciona esto.
  • La columna debe declararse CHARACTER SET utf8 (o utf8mb4). Soluciona esto.
  • HTML debe comenzar con <meta charset=UTF-8> .

Si los datos parecen correctos, pero no se ordenan correctamente, entonces ha elegido la intercalación incorrecta, o no hay una intercalación que se adapte a sus necesidades, o tiene Codificación doble .

Codificación doble se puede confirmar haciendo SELECT .. HEX .. descrito anteriormente.

é should come back C3A9, but instead shows C383C2A9
The Emoji 👽 should come back F09F91BD, but comes back C3B0C5B8E28098C2BD

Es decir, el hexadecimal es aproximadamente el doble de largo de lo que debería ser. Esto se debe a la conversión de latin1 (o lo que sea) a utf8, luego se tratan esos bytes como si fueran latin1 y se repite la conversión. funcionan correctamente porque está, por ejemplo, ordenando como si la cadena fuera Se�or .

Corregir los datos, cuando sea posible

Para Truncamiento y signos de interrogación , los datos se pierden.

Para Mojibake / Codificación doble , ...

Para diamantes negros , ...

Las correcciones se enumeran aquí. (5 arreglos diferentes para 5 situaciones diferentes; elija con cuidado):http://mysql. rjweb.org/doc.php/charcoll#arreglos_para_varios_casos