Questo problema affligge i partecipanti di questo sito e molti altri.
Hai elencato i cinque casi principali di CHARACTER SET
problemi.
Best practice
Andando avanti, è meglio usare CHARACTER SET utf8mb4
e COLLATION utf8mb4_unicode_520_ci
. (È in arrivo una versione più recente delle regole di confronto Unicode.)
utf8mb4
è un superset di utf8
in quanto gestisce codici utf8 a 4 byte, necessari per Emoji e alcuni cinesi.
Al di fuori di MySQL, "UTF-8" si riferisce a tutte le codifiche di dimensioni, quindi effettivamente uguali a utf8mb4
di MySQL , non utf8
.
Di seguito cercherò di utilizzare tali ortografie e lettere maiuscole per distinguere all'interno di MySQL dall'esterno.
Panoramica di ciò che dovresti fare
- Imposta il tuo editor, ecc. su UTF-8.
- I moduli HTML dovrebbero iniziare come
<form accept-charset="UTF-8">
. - Fai codificare i tuoi byte come UTF-8.
- Stabilire UTF-8 come codifica utilizzata nel client.
- Fai dichiarare la colonna/tabella
CHARACTER SET utf8mb4
(Controlla conSHOW CREATE TABLE
.) <meta charset=UTF-8>
all'inizio dell'HTML- Le routine memorizzate acquisiscono il set di caratteri/le regole di confronto correnti. Potrebbero aver bisogno di essere ricostruiti.
Maggiori dettagli per i linguaggi informatici (e le sue seguenti sezioni)
Verifica i dati
Visualizzazione dei dati con uno strumento o con SELECT
non ci si può fidare. Troppi client di questo tipo, in particolare i browser, cercano di compensare le codifiche errate e mostrano il testo corretto anche se il database è alterato. Quindi, scegli una tabella e una colonna con del testo non inglese e fai
SELECT col, HEX(col) FROM tbl WHERE ...
L'esadecimale per UTF-8 correttamente memorizzato sarà
- Per uno spazio vuoto (in qualsiasi lingua):
20
- Per l'inglese:
4x
,5x
,6x
o7x
- Per la maggior parte dell'Europa occidentale, le lettere accentate dovrebbero essere
Cxyy
- Cirillico, ebraico e farsi/arabo:
Dxyy
- La maggior parte dell'Asia:
Exyyzz
- Emoji e alcuni cinesi:
F0yyzzww
- Maggiori dettagli
Cause specifiche e soluzioni dei problemi riscontrati
troncato testo (Se
per Señor
):
- I byte da memorizzare non sono codificati come utf8mb4. Risolvi questo.
- Inoltre, verifica che la connessione durante la lettura sia UTF-8.
Diamanti neri con punti interrogativi (Se�or
per Señor
); uno di questi casi esiste:
Caso 1 (i byte originali erano non UTF-8):
- I byte da memorizzare non sono codificati come utf8. Risolvi questo.
- La connessione (o
SET NAMES
) per ilINSERTing
e ilSELECT
non era utf8/utf8mb4. Risolvi questo. - Inoltre, controlla che la colonna nel database sia
CHARACTER SET utf8
(o utf8mb4).
Caso 2 (i byte originali erano UTF-8):
- La connessione (o
SET NAMES
) per ilSELECT
non era utf8/utf8mb4. Risolvi questo. - Inoltre, controlla che la colonna nel database sia
CHARACTER SET utf8
(o utf8mb4).
I diamanti neri si verificano solo quando il browser è impostato su <meta charset=UTF-8>
.
Punti interrogativi (quelli normali, non diamanti neri) (Se?or
per Señor
):
- I byte da memorizzare non sono codificati come utf8/utf8mb4. Risolvi questo.
- La colonna nel database non è
CHARACTER SET utf8
(o utf8mb4). Aggiustalo. (UsaSHOW CREATE TABLE
.) - Inoltre, verifica che la connessione durante la lettura sia UTF-8.
Mojibake (Señor
per Señor
):(Questa discussione si applica anche a Doppia codifica , che non è necessariamente visibile.)
- I byte da archiviare devono essere codificati in UTF-8. Risolvi questo.
- La connessione durante
INSERTing
eSELECTing
il testo deve specificare utf8 o utf8mb4. Risolvi questo. - La colonna deve essere dichiarata
CHARACTER SET utf8
(o utf8mb4). Risolvi questo. - HTML dovrebbe iniziare con
<meta charset=UTF-8>
.
Se i dati sembrano corretti, ma non vengono ordinati correttamente, significa che non hai selezionato le regole di confronto sbagliate, o non ci sono regole di confronto adatte alle tue esigenze, oppure hai una doppia codifica .
Doppia codifica può essere confermato facendo il SELECT .. HEX ..
descritto sopra.
é should come back C3A9, but instead shows C383C2A9
The Emoji 👽 should come back F09F91BD, but comes back C3B0C5B8E28098C2BD
Cioè, l'esadecimale è circa il doppio di quanto dovrebbe essere. Ciò è causato dalla conversione da latin1 (o qualsiasi altra cosa) a utf8, quindi trattando quei byte come se fossero latin1 e ripetendo la conversione. L'ordinamento (e il confronto) non funziona correttamente perché, ad esempio, ordina come se la stringa fosse Señor
.
Correzione dei dati, ove possibile
Per troncamento e Punti interrogativi , i dati vengono persi.
Per Mojibake / Doppia codifica , ...
Per diamanti neri , ...
Le correzioni sono elencati qui. (5 diverse correzioni per 5 diverse situazioni; scegli con attenzione):http://mysql. rjweb.org/doc.php/charcoll#fixes_for_various_cases