Come fare in modo che MySQL gestisca correttamente UTF-8


102

Una delle risposte a una domanda che ho posto ieri mi ha suggerito di assicurarmi che il mio database possa gestire correttamente i caratteri UTF-8. Come posso farlo con MySQL?


4
Spero davvero che otteniamo una risposta completa, che copre varie versioni di MySQL, incompatibilità, ecc.
Edward Z. Yang


1
@ EdwardZ.Yang - Introduzione di MySQL 4.1 CHARACTER SETs; 5.1.24 ha pasticciato con il confronto del tedesco diesis (ß), che è stato corretto aggiungendo un altro confronto in 5.1.62 (probabilmente peggiorando le cose); 5.5.3 compilato utf8 con il nuovo set di caratteri utf8mb4.
Rick James,

1
Questa domanda è più o meno la stessa di questa .. Dai un'occhiata a stackoverflow.com/questions/3513773/…
Nyein Aung

Vale la pena sottolineare che la maggior parte di queste risposte sono semplicemente sbagliate. Non utilizzare utf8. Supporta solo caratteri fino a 3 byte. Il set di caratteri corretto da utilizzare in MySQL è utf8mb4.
Brendan Byrd

Risposte:


89

Aggiornare:

Risposta breve: dovresti quasi sempre utilizzare il utf8mb4set di caratteri e le utf8mb4_unicode_ciregole di confronto.

Per modificare il database:

ALTER DATABASE dbname CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Vedere:

Risposta originale:

MySQL 4.1 e versioni successive ha un set di caratteri predefinito UTF-8. Puoi verificarlo nel tuo my.cnffile, ricordati di impostare sia client che server ( default-character-sete character-set-server).

Se disponi di dati esistenti che desideri convertire in UTF-8, esegui il dump del database e importalo nuovamente come UTF-8 assicurandoti che:

  • utilizzare SET NAMES utf8prima di interrogare / inserire nel database
  • utilizzare DEFAULT CHARSET=utf8quando si creano nuove tabelle
  • a questo punto il tuo client e server MySQL dovrebbe essere in UTF-8 (vedi my.cnf). ricorda che tutte le lingue che usi (come PHP) devono essere anche UTF-8. Alcune versioni di PHP utilizzeranno la propria libreria client MySQL, che potrebbe non essere compatibile con UTF-8.

Se vuoi migrare i dati esistenti ricordati di fare prima il backup! Quando le cose non vanno come pianificato, possono verificarsi molte strane operazioni di frammentazione dei dati!

Alcune risorse:


29
La mia comprensione è che utf8in MySQL si fa riferimento solo a un piccolo sottoinsieme di Unicode completo. Dovresti usare utf8mb4invece per forzare il supporto completo. Vedere mathiasbynens.be/notes/mysql-utf8mb4 "Per molto tempo ho utilizzato il set di caratteri utf8 di MySQL per database, tabelle e colonne, assumendo che fosse mappato sulla codifica UTF-8 descritta sopra."
Aaron McDaid

7
MySQL non ha mai avuto un set di caratteri predefinito di UTF-8. 4.1 e 5.x fino all'ultimo 5.7 sono tutti usati latin1e latin1_swedish_ciper il set di caratteri e le regole di confronto predefiniti. Vedere "Server set di caratteri e regole di confronto" pagina del manuale di MySQL per la conferma: dev.mysql.com/doc/refman/5.1/en/charset-server.html
Animismo

2
@TimTisdall Non devi preoccuparti di utf8mb4occupare spazio di archiviazione aggiuntivo quando la maggior parte del testo è ASCII. Sebbene le charstringhe siano preallocate, le varcharstringhe non lo sono - vedere le ultime righe in questa pagina di documentazione . Ad esempio, char(10)riserverà pessimisticamente 40 byte sotto utf8mb4, ma varchar(10)allocherà i byte in linea con la codifica a lunghezza variabile.
Kevin A. Naudé

1
@ Kevin Penso che tu abbia letto male. Penso che la lunghezza massima della riga sia 64k. Puoi creare un campo utf8mb4 solo 1/4 perché doveva riservare quella quantità di spazio. Quindi, anche se è ASCII, puoi inserire solo 16k caratteri.
Tim Tisdall

1
@TimTisdall Oh, stai parlando di limiti superiori. Sì, quelli sono inferiori. Fortunatamente, le versioni correnti di mysql si aggiorneranno automaticamente da varchar(n)al texttipo di dati se si tenta di modificare un varchar(n)campo in modo che sia più grande della dimensione in byte ammissibile (durante l'emissione di un avviso). Un indice avrà anche un limite superiore del caso peggiore inferiore e ciò potrebbe presentare altri problemi.
Kevin A. Naudé

44

Per renderlo "permanente", in my.cnf:

[client]
default-character-set=utf8
[mysqld]
character-set-server = utf8

Per verificare, vai al client e mostra alcune variabili:

SHOW VARIABLES LIKE 'character_set%';

Verifica che siano tutti utf8, tranne ..._filesystem, che dovrebbe essere binarye ..._dir, che punta da qualche parte nell'installazione di MySQL.


Non ha funzionato nel mio caso, ma ho creato comunque il file my.cf in / etc con il contenuto dato. Ho usatocreate table my_name(field_name varchar(25) character set utf8);
Marek Bar

"SHOW VARIABLES LIKE 'character_set%';" comando mi ha rivelato il problema con la mia connessione. Grazie!
javsmo

1
Questo non è corretto. Ciò che MySQL chiama utf8non è UTF-8 "completo".
TWR Cole

32

MySQL 4.1 e versioni successive ha un set di caratteri predefinito che chiama utf8ma che in realtà è solo un sottoinsieme di UTF-8 (consente solo caratteri a tre byte e più piccoli).

Usa utf8mb4come set di caratteri se vuoi UTF-8 "completo".


5
Sicuramente d'accordo, questa è l'unica risposta corretta. utf8non include caratteri come le emoticon. utf8mb4fa. Controlla questo per maggiori informazioni su come aggiornare: mathiasbynens.be/notes/mysql-utf8mb4
jibai31

@Basti - Per lo più corretto (latin1 era l'impostazione predefinita fino a poco tempo fa) e non completo (non discute l'inserimento / selezione corretto dei dati con codifica utf8, né la visualizzazione in html).
Rick James,

Con tutto il rispetto, @RickJames, Basti ha detto "finora" - Non ricordo di aver visto la tua risposta quando l'ho pubblicata.
TWR Cole

Purtroppo, ci sono circa 5 sintomi distintamente diversi dei problemi di utf8 e circa 4 cose che i programmatori sbagliano per causare problemi. La maggior parte delle risposte sottolinea solo una cosa che potrebbe dover essere risolta. La domanda originale era ampia, quindi la risposta richiedeva tutte e 4. Forse Basti conosceva un sintomo per il quale il tuo aspetto era la soluzione.
Rick James

8
Per inciso, vorrei fermarmi un momento e dare al team di MySQL uno sguardo duro e davvero buono. o_o WTF stavate pensando ragazzi? Ti rendi conto di quanta confusione hai seminato creando una tabella codici nel tuo programma chiamata "utf8" che in realtà non è UTF-8? Dannati stronzi. </rant>
TWR Cole

20

La risposta breve: utilizzare utf8mb4in 4 posizioni:

  • I byte nel tuo client sono utf8, non latin1 / cp1251 / ecc.
  • SET NAMES utf8mb4 o qualcosa di equivalente quando si stabilisce la connessione del client a MySQL
  • CHARACTER SET utf8mb4 su tutte le tabelle / colonne - tranne le colonne che sono rigorosamente ascii / hex / country_code / zip_code / ecc.
  • <meta charset charset=UTF-8>se esegui l'output in HTML. (Sì, l'ortografia è diversa qui.)

Maggiori informazioni ;
UTF8 fino in fondo

I link di cui sopra forniscono la "risposta canonica dettagliata è necessaria per affrontare tutte le preoccupazioni". - C'è un limite di spazio su questo forum.

modificare

Oltre a CHARACTER SET utf8mb4contenere "tutti" i personaggi del mondo, COLLATION utf8mb4_unicode_520_ciè discutibile la "migliore raccolta completa" da utilizzare. (Esistono anche regole di confronto in turco, spagnolo, ecc. Per coloro che desiderano le sfumature in quelle lingue.)


Il mio nuovo link su come eseguire il debug dei problemi utf8 dall'output che ottieni.
Rick James

Perché unicode_520_ci non è il migliore in assoluto: stackoverflow.com/a/49982378/62202
Louis

@Louis - E come ho detto, gli utenti spagnoli e turchi (oltre che polacchi) potrebbero non essere contenti. "Best all-around" tende a ferire tutti un po '. MySQL 8.0 ha una "migliore" collation ancora più recente: utf8mb4_0900_ai_ci . Ahimè, ancora una volta L = £.
Rick James il

4

Il set di caratteri è una proprietà del database (predefinito) e della tabella. Puoi dare un'occhiata (comandi MySQL):

show create database foo; 
> CREATE DATABASE  `foo`.`foo` /*!40100 DEFAULT CHARACTER SET latin1 */

show create table foo.bar;
> lots of stuff ending with
> ) ENGINE=InnoDB AUTO_INCREMENT=252 DEFAULT CHARSET=latin1

In altre parole; è abbastanza facile controllare il set di caratteri del database o modificarlo:

ALTER TABLE `foo`.`bar` CHARACTER SET utf8;

1
Questo non è corretto. Ciò che MySQL chiama utf8non è UTF-8 "completo".
TWR Cole


2

Ho seguito la soluzione di Javier, ma ho aggiunto alcune righe diverse in my.cnf:

[myslqd]
skip-character-set-client-handshake
collation_server=utf8_unicode_ci
character_set_server=utf8 

Ho trovato questa idea qui: http://dev.mysql.com/doc/refman/5.0/en/charset-server.html nel primo / unico commento dell'utente in fondo alla pagina. Dice che la stretta di mano con il client per saltare il set di caratteri ha una certa importanza.


Questa risposta non amata e senza voto è stata l'unica cosa che mi ha aiutato! Quindi ottiene il mio voto, questo è dannatamente sicuro. skip-character-set-client-handshakeera la chiave.
Marcus


0

Imposta il tuo database collationper UTF-8 poi applicare table collational database predefinito.


-1

La tua risposta è che puoi configurare dalle Impostazioni MySql. Nella mia risposta potrebbe esserci qualcosa fuori contesto, ma anche sapere è un aiuto per te.
come configurare Character SeteCollation .

Per le applicazioni che memorizzano i dati utilizzando il set di caratteri MySQL predefinito e le regole di confronto ( latin1, latin1_swedish_ci), non dovrebbe essere necessaria alcuna configurazione speciale. Se le applicazioni richiedono l'archiviazione dei dati utilizzando un set di caratteri o regole di confronto diverso, è possibile configurare le informazioni sul set di caratteri in diversi modi:

  • Specifica le impostazioni dei caratteri per database. Ad esempio, le applicazioni che utilizzano un database potrebbero richiedere utf8, mentre le applicazioni che utilizzano un altro database potrebbero richiedere sjis.
  • Specificare le impostazioni dei caratteri all'avvio del server. Ciò fa sì che il server utilizzi le impostazioni fornite per tutte le applicazioni che non prevedono altre disposizioni.
  • Specificare le impostazioni dei caratteri al momento della configurazione , se si crea MySQL dal sorgente. Ciò fa sì che il server utilizzi le impostazioni fornite per tutte le applicazioni, senza doverle specificare all'avvio del server.

Gli esempi mostrati qui per la tua domanda per impostare il set di caratteri utf8, qui anche impostare le regole di confronto per più utili ( utf8_general_cicollation`).

Specifica le impostazioni dei caratteri per database

  CREATE DATABASE new_db
  DEFAULT CHARACTER SET utf8
  DEFAULT COLLATE utf8_general_ci;

Specificare le impostazioni dei caratteri all'avvio del server

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci

Specificare le impostazioni dei caratteri al momento della configurazione di MySQL

shell> cmake . -DDEFAULT_CHARSET=utf8 \
           -DDEFAULT_COLLATION=utf8_general_ci

Per visualizzare i valori del set di caratteri e delle variabili di sistema delle regole di confronto applicabili alla connessione, utilizzare queste istruzioni:

SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';

Questa potrebbe essere una risposta lunga ma c'è tutto il modo che puoi usare. Spero che la mia risposta sia utile per te. per maggiori informazioni http://dev.mysql.com/doc/refman/5.7/en/charset-applications.html


-2

SET NAMES UTF8

Questo è il trucco


2
Sebbene l'uso di SET NAMES UTF8(o UTF8mb4) sia corretto, non spieghi cosa fa (set di caratteri utilizzato per questa connessione). "Questo fa il trucco" sembra che risolverebbe il problema (fare in modo che MySQL gestisca correttamente UTF-8), ma molti database MySQL sono impostati su latin1 per impostazione predefinita, quindi non sarebbe una soluzione adeguata. Vorrei modificare il set di caratteri predefinito e i set di caratteri della tabella in utf8mb4. In realtà, questa risposta è piuttosto incompleta, quindi l'ho sottovalutata.
basic6

-2

CONNESSIONE DEL DATABASE A UTF-8

$connect = mysql_connect('$localhost','$username','$password') or die(mysql_error());
mysql_set_charset('utf8',$connect);
mysql_select_db('$database_name','$connect') or die(mysql_error());

-3

Imposta la connessione al database su UTF8:

  if($handle = @mysql_connect(DB_HOST, DB_USER, DB_PASS)){          
         //set to utf8 encoding
         mysql_set_charset('utf8',$handle);
  }

Se si esegue PHP, non utilizzare l' mysql_*interfaccia deprecata . Passa a mysqli_*o PDO.
Rick James

-3

Riuscì a trovare una soluzione. Ha eseguito quanto segue come specificato su http://technoguider.com/2015/05/utf8-set-up-in-mysql/

SET NAMES UTF8;
set collation_server = utf8_general_ci;
set default-character-set = utf8;
set init_connect = SET NAMES utf8′;
set character_set_server = utf8;
set character_set_client = utf8;

Le ultime due righe sono ridondanti, poiché la prima include già quelle: dev.mysql.com/doc/refman/5.0/en/charset-connection.html
DanielM

Inoltre non è una soluzione completa. Le colonne hanno bisogno CHARACTER SET utf8. rootnon eseguirà l'importantissimo init_connect.
Rick James
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.