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 conSHOW 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.
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, o7x - 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 elINSERTy elSELECTno 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) paraSELECTno 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. (UtiliceSHOW 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
INSERTingySELECTingel 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):https://mysql. rjweb.org/doc.php/charcoll#arreglos_para_varios_casos