Mysql
 sql >> Database >  >> RDS >> Mysql

Problemi con i caratteri UTF-8; quello che vedo non è quello che ho memorizzato

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

UTF- 8 fino in fondo

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 o 7x
  • 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 il INSERTing e il SELECT 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 il SELECT 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. (Usa SHOW 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 e SELECTing 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