Mélange illégal de classements Erreur MySQL


124

J'obtiens cette étrange erreur lors du traitement d'un grand nombre de données ...

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 昔 ã‹ã‚‰ ã‚ã‚‹ å ´æ‰€'

Que puis-je faire pour résoudre ce problème? Puis-je échapper à la chaîne d'une manière ou d'une autre pour que cette erreur ne se produise pas, ou dois-je changer le codage de ma table d'une manière ou d'une autre, et si oui, comment dois-je le changer?


cette erreur, c'est un injectable ou pas?
hamza irizaj

1
Est-ce que cela répond à votre question? Erreur de mélange illégal de collations dans MySql
Farhan

Réponses:


288
SET collation_connection = 'utf8_general_ci';

puis pour vos bases de données

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 se faufile parfois en suédois sans raison valable.


3
@Ben: Merci pour une solution directement copiable. Cela m'a fait gagner beaucoup de temps.
Pistos

15
@Ben: Il a été initialement développé par une société suédoise ... C'est la raison derrière le réglage initial ennuyeux de latin1_swedish_ci .. :(
Vajk Hermecz

1
Je n'avais pas les autorisations pour faire la première déclaration mais cela fonctionnait simplement en faisant le tableau
Rob Sedgwick

Je t'aime pour ça! : P
prateekkathal

Il semble que cela fonctionne pour beaucoup de gens, mais malheureusement, j'ai toujours ce problème même après avoir essayé tous les appareils de ce fil. Le classement par défaut de ma base de données refuse obstinément de changer de 'ucs2_bin', donc j'ai même essayé de changer toutes les tables et le classement de connexion en 'usc2_bin' mais j'obtiens toujours l'erreur "Erreur SQL (1267): mélange illégal de classements (utf8_general_ci, IMPLICIT) et (ucs2_bin, IMPLICIT) pour l'opération '=' ".
bikeman868

15

Vous devez définir à la fois le codage de votre table et celui de la connexion sur UTF-8:

ALTER TABLE keywords CHARACTER SET UTF8; -- run once

et

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

Les deux sont-ils nécessaires ou puis-je simplement faire l'un d'entre eux?
Cliquez sur Upvote le

ALTER DATABASE myDbDEFAULT CHARACTER SET utf8 COLLATE utf8_bin. Cela fonctionnerait-il? Ceci est fait pour que cela affecte toutes mes tables, pas seulement l'une d'entre elles
Cliquez sur Upvote le

1
ALTER DATABASE ne changera pas vos paramètres de table actuels, seulement ceux nouvellement créés. Cependant, cela ne fera pas de mal de modifier le jeu de caractères par défaut pour la base de données.
Quassnoi

SET NAMES et SET CHARACTER SET changeront le codage de votre connexion. Vous devez émettre ces commandes à chaque fois que vous vous connectez. Votre bibliothèque cliente peut prendre en charge une méthode plus élégante pour le faire (php :: mysqli le fait, php :: mysql ne le fait pas).
Quassnoi

Cela semble fonctionner pour le moment, j'accepterai après quelques tests supplémentaires. Les secondes requêtes doivent-elles être exécutées une fois ou au début de chaque script?
Cliquez sur Upvote le

13
CONVERT(column1 USING utf8)

Résout mon problème. Où colonne1 est la colonne qui me donne cette erreur.


Pour moi, cela a fonctionné: CONVERT ("column1" USING LATIN1)
shasi kanth

4

Utilisez l'instruction suivante pour l'erreur

faites attention à vos données, prenez une sauvegarde si les données sont dans le tableau.

 ALTER TABLE your_table_name CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;

2

En général, le meilleur moyen est de modifier le classement des tables. Cependant, j'ai une ancienne application et je ne suis pas vraiment en mesure d'estimer le résultat si cela a des effets secondaires. Par conséquent, j'ai essayé d'une manière ou d'une autre de convertir la chaîne dans un autre format qui a résolu le problème de classement. Ce que j'ai trouvé efficace, c'est de comparer les chaînes en convertissant les chaînes en une représentation hexadécimale de ses caractères. Sur la base de données cela se fait avec HEX(column).Pour PHP, vous pouvez utiliser cette fonction:

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);
}

Lorsque vous effectuez la requête de base de données, votre chaîne UTF8 d'origine doit d'abord être convertie en une chaîne iso (par exemple en utilisant utf8_decode()en PHP) avant de l'utiliser dans la base de données. En raison du type de classement, la base de données ne peut pas contenir de caractères UTF8, le comparisme devrait donc fonctionner même si cela modifie la chaîne d'origine (la conversion des caractères UTF8 qui n'existent pas dans le jeu de caractères ISO entraîne un? Ou ceux-ci sont entièrement supprimés). Assurez-vous simplement que lorsque vous écrivez des données dans la base de données, vous utilisez la même conversion UTF8 en ISO.


2

J'ai créé ma table à l'origine avec CHARSET = latin1 . Après la conversion de table en utf8, certaines colonnes n'ont pas été converties, mais ce n'était pas vraiment évident. Vous pouvez essayer d'exécuter SHOW CREATE TABLE my_table;et voir quelle colonne n'a pas été convertie ou simplement corriger le jeu de caractères incorrect sur la colonne problématique avec la requête ci-dessous (modifiez la longueur de varchar et CHARSET et COLLATE selon vos besoins):

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

2

Changer le jeu de caractères de la table en utf8

ALTER TABLE votre_nom_table CONVERT TO CHARACTER SET utf8


0

Après avoir effectué vos corrections répertoriées dans la première réponse, modifiez les paramètres par défaut de votre serveur.

Dans votre " /etc/my.cnf.d/server.cnf " ou où qu'il se trouve, ajoutez les valeurs par défaut à la section [mysqld] pour qu'elle ressemble à ceci:

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

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


0

J'ai trouvé que l'utilisation cast()était la meilleure solution pour moi:

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

Il y a aussi une convert()fonction. Plus de détails ici

Une autre ressource ici


0

Mon compte utilisateur n'avait pas les autorisations pour modifier la base de données et la table, comme suggéré dans cette solution .

Si, comme moi, vous ne vous souciez pas du classement des caractères (vous utilisez l'opérateur '='), vous pouvez appliquer le correctif inverse. Exécutez ceci avant votre SELECT:

SET collation_connection = 'latin1_swedish_ci';
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.