IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PHP & Base de données Discussion :

Uncaught mysqli_sql_exception: Illegal mix of collations (utf8mb4_unicode_ci,IMPLICIT) and (utf8mb3_general_c


Sujet :

PHP & Base de données

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    718
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 718
    Par défaut Uncaught mysqli_sql_exception: Illegal mix of collations (utf8mb4_unicode_ci,IMPLICIT) and (utf8mb3_general_c
    Bonjour,

    Uncaught mysqli_sql_exception: Illegal mix of collations (utf8mb4_unicode_ci,IMPLICIT) and (utf8mb3_general_ci,COERCIBLE) for operation '='


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    if (!Empty ($vv[22]))
    {
    if (isSet ($Fab_Tab[$vv[22]])) $vv[22] = $Fab_Tab[$vv[22]];
     
    $requete = "SELECT col_1 FROM table WHERE col_2 = '" . $vv[22] . "'";
     
    if (mysqli_num_rows (mysqli_query ($connexion, $requete)) == 0) $Tab_Equi[$vv[0]] = $vv[22];
     
    }

    col_1 = INT
    col_2 = varchar(40) INTERCLASSEMENT utf8mb4_unicode_ci

    Je ne comprends pas l'erreur.
    Je suppose qu'il faut ajouter un COLLATE quelque part mais où ?

    Merci d'avance de votre aide.

  2. #2
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 544
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 544
    Billets dans le blog
    10
    Par défaut
    bonjour,

    Ici Col_1 n'est pas en cause puisque cette colonne n'est ni comparée à une valeur ou une autre colonne, ni triée ou groupée.
    C'est donc Col_2 dont la collation est différente de la variable avec laquelle elle est comparée.
    Mais visiblement, le jeu de caractères est lui aussi différent.
    Il est donc préférable d'utiliser une variable créée dans le même jeu de caractères et la même collation ou d'opérer la conversion sur la variable et non pas sur Col_2, car sinon la clause WHERE ne sera plus sargable (index non éligibles et performances dégradées)

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    718
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 718
    Par défaut
    Bonjour,

    Merci de ton suvi.

    col_2 = varchar(40) INTERCLASSEMENT utf8mb4_unicode_ci

    Dois-je utiliser iconv (utf8mb3_general_ci, utf8mb4_unicode_ci, $vv[22]) ?

    Le problème vient-il du codage de $vv[22] dans le fichier externe ?

    Merci d'avance pour tes précisions.

  4. #4
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 982
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 982
    Par défaut
    À ta place je laisserais tomber les iconv et autres mb_convert pour le moment.

    Si MySQL suppose qu'un littéral (le contenu de $vv[22] dans la requête) est encodé en utf8mb3 avec la collation utf8mb3_general_ci, c'est parce qu'il le déduit de l'encodage de connection.
    Donc pour être raccord avec celui de ta table, tu dois indiquer l'encodage et éventuellement la collation à utiliser lorsque tu crées ta connexion avec le client MySQLi. Exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $connexion = mysqli_connect('serveurMySQL', 'utilisateur', 'motdepasse', 'basededonnees');
    mysqli_set_charset($connexion, 'utf8mb4');
    Tu peux également préciser une collation en ajoutant à la suite:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mysqli_query($connexion, 'SET collation_connection = utf8mb4_unicode_ci');
    Mais ça ne devrait pas être nécessaire puisque utf8mb4_unicode_ci est la collation par défaut pour l'encodage utf8mb4.

    NB: suivant ta version de MySQL, certaines collations plus récentes que utf8mb4_unicode_ci (se rapportant à une version plus récente de l'unicode) peuvent être disponibles comme utf8mb4_unicode_520_ci ou utf8mb4_0900_as_ci (520 indique la version 5.2 d'unicode, 0900 indique la version 9). Dans ce cas tu peux projeter de passer toute ta base avec l'une de ces collations.

    Voilà pour ce qui est de la connexion au serveur MySQL, mais ça ne te dispense pas de bien vérifier que tes données externes sont correctement encodées en UTF-8 avant de les balancer dans ta table.

    PS: je suis estomaqué que tu n'utilises toujours pas une requête préparée.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    718
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 718
    Par défaut
    Bonjour CosmoKnacki,

    MERCI de ton suivi.

    En préambule :

    Citation Envoyé par CosmoKnacki
    PS: je suis estomaqué que tu n'utilises toujours pas une requête préparée.
    J'utilise les requêtes préparées quand il y a risque d'injection SQL.
    Ici il s'agit d'une requête d'administration à laquelle en gros je suis le seul à avoir accès.
    Je sais que tu as raison, qu'il faut partout des requêtes préparées, mais je dois me concentrer sur le plus urgent.

    Autrement j'utilise déjà mysqli_set_charset ($connexion, 'utf8'); derrière mysqli_connect ().

    En fait $vv[22] provient d'un fichier envoyé par un fournisseur.
    C'est supposé être une référence fabricant, une suite de chiffres et de lettres assez courte.

    Mais parfois dans le fichier à la place de la référence fabricant il y a le descriptif avec plein de caractères accentués et autre pétouilles qui provoquent l'erreur fatale.

    J'ai trouvé un moyen simple de régler ce problème particulier.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $vv[22] = htmlentities ($vv[22], ENT_QUOTES, 'UTF-8' );
     
    // Bonne valeur
    SELECT col_1 FROM table WHERE col_2 = '060018'
     
    // Mauvaise valeur mais ne provoque plus d'erreur fatale
    SELECT col_1 FROM table WHERE col_2 = ' 1080p@60m (Cat 5e/6) / 70 m (Cat 6a) 4096 x 2160 / 3840 x 2160 @ 60Hz (4:2:0)'

  6. #6
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 982
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 982
    Par défaut
    Citation Envoyé par boteha Voir le message
    Autrement j'utilise déjà mysqli_set_charset ($connexion, 'utf8'); derrière mysqli_connect ().
    Sauf que c'est utf8mb4 qu'il faut mettre (le même encodage que ta table) et pas utf8 (qui correspond pour MySQL >= 8 à utf8mb3 avec comme collation par défaut utf8mb3_general_ci). C'est précisément le sens de ton message d'erreur.




    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $vv[22] = htmlentities ($vv[22], ENT_QUOTES, 'UTF-8' );
    Ça c'est mettre la poussière sous le tapis. Si en plus du problème de configuration de la collation de ta session MySQL, tu as aussi un problème d'encodage de ton fichier, tu dois le résoudre et pas bricoler. Tout ce que tu vas faire avec ce code, c'est stocker des entités html dans ta base, ce qui prend de la place pour rien et risque de compliquer les recherches. Et pour ce qui est des éventuels quotes contenus dans la chaîne, encore une fois: fais une requête préparée!
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    718
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 718
    Par défaut
    Bonjour CosmoKnacki,

    Encore merci de ton aide.

    Citation Envoyé par CosmoKnacki
    Sauf que c'est utf8mb4 qu'il faut mettre (le même encodage que ta table) et pas utf8 (qui correspond pour MySQL >= 8 à utf8mb3 avec comme collation par défaut utf8mb3_general_ci). C'est précisément le sens de ton message d'erreur.
    D'accord, je vais essayer.

    Citation Envoyé par CosmoKnacki
    Tout ce que tu vas faire avec ce code, c'est stocker des entités html dans ta base, ce qui prend de la place pour rien et risque de compliquer les recherches.
    Je ne stocke aucune entité html dans la base.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $vv[22] = htmlentities ($vv[22], ENT_QUOTES, 'UTF-8' );
     
    // Bonne valeur
    SELECT col_1 FROM table WHERE col_2 = '060018'
    Si la valeur est bonne aucun caractère n'est transformé par htmlentities.
    Si la valeur est mauvaise aucun résultat ne sera retourné.
    Je traite $vv[22] transmis par le fournisseur mais pas la base.

  8. #8
    Membre éclairé
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    718
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 718
    Par défaut
    Bonjour,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mysqli_set_charset ($connexion, 'utf8mb4');
    J'ai fait le changement, cela semble ne pas poser de problème.

    Toutes les colonnes de type text dans la base sont utf8mb4_unicode_ci, sauf quelques-une qui doivent être sensibles à la casse et qui sont en utf8mb4_bin.

    Par contre, si j'enlève $vv[22] = htmlentities ($vv[22], ENT_QUOTES, 'UTF-8' ); je me prends une erreur fatale mais à présent pour mauvaise syntaxe SQL.

    Comme déjà expliqué cela provient du fichier du fournisseur un peu bugué et dans lequel la référence fabricant est parfois remplacée par la description du produit sur plusieurs lignes...

    htmlentities évite l'erreur fatale et comme déjà expliqué je n'ai pas besoin de toucher à ma base.
    C'est pour moi une solution satisfaisante surtout dans un script d'administration qui n'a pas besoin d'être super-performant.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 16
    Dernier message: 03/10/2023, 09h50
  2. Réponses: 6
    Dernier message: 08/09/2009, 00h19
  3. [MySQL] Illegal mix of collations
    Par lodan dans le forum PHP & Base de données
    Réponses: 6
    Dernier message: 08/11/2007, 16h08
  4. Illegal mix of collations avec UNION ALL
    Par lodan dans le forum Outils
    Réponses: 1
    Dernier message: 03/05/2007, 18h05
  5. Illegal mix of collations
    Par Gildas Huart dans le forum Requêtes
    Réponses: 2
    Dernier message: 23/02/2006, 10h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo