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 elINSERT
y elSELECT
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
) paraSELECT
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. (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
INSERTing
ySELECTing
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