Miscela illegale di regole di confronto Errore MySQL


124

Ricevo questo strano errore durante l'elaborazione di un gran numero di dati ...

Error Number: 1267

Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '='

SELECT COUNT(*) as num from keywords WHERE campaignId='12' AND LCASE(keyword)='hello again 昔 ã‹ã‚‰ ã‚ã‚‹ å ´æ‰€'

Cosa posso fare per risolvere questo problema? Posso eseguire l'escape della stringa in qualche modo in modo che questo errore non si verifichi o devo modificare in qualche modo la codifica della mia tabella e, in tal caso, in cosa dovrei cambiarla?


questo errore è un iniettabile o no?
hamza irizaj

Risposte:


288
SET collation_connection = 'utf8_general_ci';

quindi per i tuoi database

ALTER DATABASE your_database_name CHARACTER SET utf8 COLLATE utf8_general_ci;

ALTER TABLE your_table_name CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;

MySQL si intrufola in svedese a volte senza motivo ragionevole.


3
@ Ben: grazie per una soluzione direttamente copiabile. Mi ha fatto risparmiare un sacco di tempo.
Pistos

15
@Ben: Inizialmente è stato sviluppato da un'azienda svedese ... Questo è il motivo dietro la fastidiosa impostazione iniziale di latin1_swedish_ci .. :(
Vajk Hermecz

1
Non avevo i permessi per fare la prima istruzione ma ha funzionato solo facendo la tabella
Rob Sedgwick

Ti amo per questo! : P
prateekkathal

Sembra che questo funzioni per molte persone, ma sfortunatamente ho ancora questo problema anche dopo aver provato tutto il dispositivo in questo thread. Le regole di confronto predefinite del database si rifiutano ostinatamente di cambiare da "ucs2_bin", quindi ho anche provato a cambiare tutte le tabelle e le regole di confronto della connessione in "usc2_bin" ma ricevo ancora l'errore "Errore SQL (1267): mix illegale di regole di confronto (utf8_general_ci, IMPLICIT) e (ucs2_bin, IMPLICIT) per l'operazione '=' ".
bikeman868

15

Dovresti impostare sia la codifica della tabella che la codifica della connessione su UTF-8:

ALTER TABLE keywords CHARACTER SET UTF8; -- run once

e

SET NAMES 'UTF8';
SET CHARACTER SET 'UTF8';

Sono necessari entrambi o posso farne solo uno?
Fai clic su Upvote

ALTER DATABASE myDbSET DI CARATTERI PREDEFINITI utf8 COLLATE utf8_bin. Funzionerebbe? Questo è fatto in modo che influenzerebbe tutte le mie tabelle, non solo una di esse
Fai clic su Upvote

1
ALTER DATABASE non modificherà le impostazioni correnti della tabella, ma solo quelle appena create. Tuttavia non farà male modificare anche il set di caratteri predefinito per il database.
Quassnoi

SET NAMES e SET CHARACTER SET cambieranno la codifica della connessione. Devi emettere questi comandi ogni volta che ti connetti. La tua libreria client può supportare un metodo più elegante per farlo (php :: mysqli lo fa, php :: mysql no).
Quassnoi

Per ora sembra funzionare, accetterò dopo qualche altro test. Le seconde query devono essere eseguite una volta o all'inizio di ogni script?
Fai clic su Upvote

13
CONVERT(column1 USING utf8)

Risolve il mio problema. Dove colonna1 è la colonna che mi dà questo errore.


Per me, ha funzionato: CONVERT ("column1" USING LATIN1)
shasi kanth

4

Usa la seguente dichiarazione per errore

fai attenzione ai tuoi dati fai il backup se i dati sono in tabella.

 ALTER TABLE your_table_name CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;

2

In generale, il modo migliore è modificare le regole di confronto della tabella. Tuttavia ho una vecchia applicazione e non sono davvero in grado di stimare il risultato se questo ha effetti collaterali. Pertanto ho provato in qualche modo a convertire la stringa in un altro formato che risolvesse il problema delle regole di confronto. Quello che ho trovato funzionante è fare il confronto delle stringhe convertendo le stringhe in una rappresentazione esadecimale dei suoi caratteri. Sul database questo viene fatto con HEX(column).Per PHP puoi usare questa funzione:

public static function strToHex($string)
{
    $hex = '';
    for ($i=0; $i<strlen($string); $i++){
        $ord = ord($string[$i]);
        $hexCode = dechex($ord);
        $hex .= substr('0'.$hexCode, -2);
    }
    return strToUpper($hex);
}

Quando si esegue la query sul database, la stringa UTF8 originale deve essere convertita prima in una stringa iso (ad esempio utilizzando utf8_decode()in PHP) prima di utilizzarla nel DB. A causa del tipo di confronto, il database non può contenere caratteri UTF8 all'interno, quindi il confronto dovrebbe funzionare anche se questo modifica la stringa originale (la conversione di caratteri UTF8 che non sono presenti nel set di caratteri ISO risulta in un? O questi vengono rimossi completamente). Assicurati solo che quando scrivi i dati nel database, utilizzi la stessa conversione da UTF8 a ISO.


2

La mia tabella era stata originariamente creata con CHARSET = latin1 . Dopo la conversione della tabella in utf8 alcune colonne non sono state convertite, tuttavia ciò non era del tutto ovvio. Puoi provare a eseguire SHOW CREATE TABLE my_table;e vedere quale colonna non è stata convertita o semplicemente correggere un set di caratteri errato sulla colonna problematica con la query di seguito (modifica la lunghezza del varchar e il CHARSET e COLLATE in base alle tue esigenze):

 ALTER TABLE `my_table` CHANGE `my_column` `my_column` VARCHAR(10) CHARSET utf8 
 COLLATE utf8_general_ci NULL;

2

Modificare il set di caratteri della tabella in utf8

ALTER TABLE your_table_name CONVERT TO CHARACTER SET utf8


0

Dopo aver apportato le correzioni elencate nella risposta in alto, modifica le impostazioni predefinite del tuo server.

In " /etc/my.cnf.d/server.cnf " o ovunque si trovi, aggiungi i valori predefiniti alla sezione [mysqld] in modo che assomigli a questo:

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

Fonte: https://dev.mysql.com/doc/refman/5.7/en/charset-applications.html


0

L'ho scoperto usando cast() era la soluzione migliore per me:

cast(Format(amount, "Standard") AS CHAR CHARACTER SET utf8) AS Amount

C'è anche un convert() funzione. Maggiori dettagli su di esso qui

Un'altra risorsa qui


0

Il mio account utente non disponeva delle autorizzazioni per modificare il database e la tabella, come suggerito in questa soluzione .

Se, come me, non ti interessa il file regole di confronto dei caratteri (stai usando l'operatore "="), puoi applicare la correzione inversa. Esegui questo prima del tuo SELECT:

SET collation_connection = 'latin1_swedish_ci';
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.