web-dev-qa-db-fra.com

Comment corriger les erreurs "Valeur de chaîne incorrecte"?

Après avoir remarqué qu'une application avait tendance à ignorer les courriels aléatoires en raison d'erreurs de valeur de chaîne incorrectes, je suis allée changer de nombreuses colonnes de texte pour utiliser le jeu de caractères de colonne utf8 et l'assemblage de colonne par défaut (utf8_general_ci) afin qu'il les accepte. Cela corrigeait la plupart des erreurs et empêchait l'application de recevoir des erreurs SQL quand elle rencontrait des courriers électroniques non latins.

Malgré cela, certains courriels font que le programme rencontre des erreurs de chaîne incorrectes: (Incorrect string value: '\xE4\xC5\xCC\xC9\xD3\xD8...' for column 'contents' at row 1)

La colonne de contenu est une donnée MEDIUMTEXT qui utilise le jeu de caractères de la colonne utf8 et l'assemblage de la colonne utf8_general_ci. Je ne peux pas basculer d’indicateurs dans cette colonne.

Gardant à l'esprit que je ne veux pas toucher ou même regarder le code source de l'application à moins que cela ne soit absolument nécessaire:

  • Quelle est la cause de cette erreur? (oui, je sais que les emails sont pleins d'ordures aléatoires, mais je pensais que utf8 serait assez permissif)
  • Comment puis-je le réparer?
  • Quels sont les effets probables d'un tel correctif?

Une chose à laquelle j’avais pensé était de passer à un utf8 varchar ([un grand nombre]) avec l’indicateur binaire activé, mais je ne connais pas bien MySQL et je ne sais pas du tout si un tel correctif a un sens.

130
Brian

"\xE4\xC5\xCC\xC9\xD3\xD8" n'est pas valide UTF-8. Testé en Python:

>>> "\xE4\xC5\xCC\xC9\xD3\xD8".decode("utf-8")
...
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 0-2: invalid data

Si vous cherchez un moyen d'éviter les erreurs de décodage dans la base de données, le codage cp1252 ("Windows 1252" ou "Windows Western European") est le codage le plus permissif qui soit. Chaque valeur d'octet est un point de code valide.

Bien sûr, cela ne va plus comprendre le véritable UTF-8, ni aucun autre codage non-cp1252, mais cela vous donne l'impression que vous n'êtes pas trop préoccupé par cela?

33
RichieHindle

Je ne suggérerais pas à Richies de répondre, parce que vous bousillez les données dans la base de données. Vous ne voudriez pas résoudre votre problème, mais essayez de le "cacher" et de ne pas être en mesure d'effectuer les opérations de base de données essentielles avec les données chiffrées.

Si vous rencontrez cette erreur, les données que vous envoyez ne sont pas codées en UTF-8 ou votre connexion n’est pas en UTF-8. D'abord, vérifiez que la source de données (un fichier, ...) vraiment est UTF-8.

Ensuite, vérifiez votre connexion à la base de données, vous devriez le faire après avoir connecté:

SET NAMES 'utf8';
SET CHARACTER SET utf8;

Ensuite, vérifiez que les tables où les données sont stockées ont le jeu de caractères utf8:

SELECT
  `tables`.`TABLE_NAME`,
  `collations`.`character_set_name`
FROM
  `information_schema`.`TABLES` AS `tables`,
  `information_schema`.`COLLATION_CHARACTER_SET_APPLICABILITY` AS `collations`
WHERE
  `tables`.`table_schema` = DATABASE()
  AND `collations`.`collation_name` = `tables`.`table_collation`
;

Enfin, vérifiez les paramètres de votre base de données:

mysql> show variables like '%colla%';
mysql> show variables like '%charac%';

Si la source, le transport et la destination sont UTF-8, votre problème a disparu;)

118
nico gawenda

Les types utf-8 de MySQL ne sont pas vraiment appropriés. Il utilise seulement trois octets par caractère et ne prend en charge que le plan multilingue de base (c’est-à-dire, pas Emoji, pas de plan astral, etc.).

Si vous devez stocker des valeurs provenant de plans Unicode supérieurs, vous avez besoin des encodages utf8mb4 .

65
moeffju

La table et les champs ont un mauvais codage. Cependant, vous pouvez les convertir en UTF-8.

ALTER TABLE logtest CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;

ALTER TABLE logtest DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

ALTER TABLE logtest CHANGE title title VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci;
30
Jiayu Wang

J'ai résolu ce problème aujourd'hui en modifiant la colonne en type 'LONGBLOB' qui stocke des octets bruts au lieu de caractères UTF-8.

Le seul inconvénient est que vous devez vous-même coder. Si un client de votre application utilise le codage UTF-8 et qu'un autre utilise le CP1252, vos courriels peuvent avoir des caractères incorrects. Pour éviter cela, utilisez toujours le même codage (par exemple, UTF-8) dans toutes vos applications.

Reportez-vous à cette page http://dev.mysql.com/doc/refman/5.0/fr/blob.html pour plus de détails sur les différences entre TEXT/LONGTEXT et BLOB/LONGBLOB. Il existe également de nombreux autres arguments sur le Web qui traitent de ces deux aspects.

21
frankshaka

En général, cela se produit lorsque vous insérez des chaînes dans des colonnes avec un codage/classement incompatible.

J'ai eu cette erreur lorsque j'avais TRIGGER, qui hérite du classement du serveur pour une raison quelconque. Et la valeur par défaut de mysql est (du moins sur Ubuntu) latin-1 avec classement suédois . Même si la base de données et toutes les tables étaient définies sur UTF-8, je n’avais pas encore défini my.cnf:

/etc/mysql/my.cnf:

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

Et cela doit lister tous les déclencheurs avec utf8- *:

select TRIGGER_SCHEMA, TRIGGER_NAME, CHARACTER_SET_CLIENT, COLLATION_CONNECTION, DATABASE_COLLATION from information_schema.TRIGGERS

Et certaines des variables listées par ceci devraient aussi avoir utf-8- * (pas de codage latin-1 ou autre):

show variables like 'char%';
8
Ondra Žižka

Commencez par vérifier si votre nom de jeu de caractères par défaut est utf8.

SELECT default_character_set_name FROM information_schema.SCHEMATA S WHERE schema_name = "DBNAME";

Si le résultat n'est pas utf8, vous devez convertir votre base de données. Au début, vous devez enregistrer un dump.

Pour modifier le codage du jeu de caractères sur UTF-8 pour toutes les tables de la base de données spécifiée, tapez la commande suivante sur la ligne de commande. Remplacez DBNAME par le nom de la base de données:

mysql --database=DBNAME -B -N -e "SHOW TABLES" | awk '{print "SET foreign_key_checks = 0; ALTER TABLE", $1, "CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; SET foreign_key_checks = 1; "}' | mysql --database=DBNAME

Pour modifier le codage du jeu de caractères en UTF-8 pour la base de données elle-même, tapez la commande suivante à l'invite mysql >. Remplacez DBNAME par le nom de la base de données:

ALTER DATABASE DBNAME CHARACTER SET utf8 COLLATE utf8_general_ci;

Vous pouvez maintenant réessayer d'écrire le caractère utf8 dans votre base de données. Cette solution m'aide lorsque j'essaie de télécharger 200 000 rangées de fichiers csv dans ma base de données. 

7
Babacar Gningue

Cette erreur signifie que la chaîne contient un codage incorrect (vous essayez par exemple de saisir une chaîne codée ISO-8859-1 dans une colonne codée UTF-8) ou que la colonne ne prend pas en charge les données que vous essayez de saisir.

En pratique, ce dernier problème est dû à une implémentation MySQL UTF-8 ne prenant en charge que les caractères UNICODE nécessitant 1 à 3 octets lors de la représentation dans UTF-8. Voir "Valeur de chaîne incorrecte" lorsque vous essayez d'insérer UTF-8 dans MySQL via JDBC? pour plus de détails.

4

Bien que votre classement soit défini sur utf8_general_ci, je suppose que le codage de caractères de la base de données, de la table ou même de la colonne peut être différent. 

ALTER TABLE tabale_name MODIFY COLUMN column_name VARCHAR(255)  
CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;

J'ai une erreur similaire (Incorrect string value: '\xD0\xBE\xDO\xB2. ...' for 'content' at row 1). J'ai essayé de changer le jeu de caractères de la colonne en utf8mb4 et ensuite, l'erreur a été remplacée par 'Data too long for column 'content' at row 1'.
Il s’est avéré que mysql me montre une erreur erronée. J'ai redéfini le jeu de caractères de la colonne sur utf8 et modifié le type de la colonne en MEDIUMTEXT. Après cela, l'erreur a disparu.
J'espère que ça aide quelqu'un.
Au fait, MariaDB dans le même cas (j’ai testé le même INSERT ici) vient de couper un texte sans erreur.

4
AVKurov

J'ai essayé toutes les solutions ci-dessus (qui apportent toutes des arguments valables), mais rien ne fonctionnait pour moi. 

Jusqu'à ce que je découvre que mes mappages de champs de table MySQL en C # utilisaient un type incorrect: MySqlDbType.Blob . Je l'ai changé en MySqlDbType.Text et maintenant je peux écrire tous les symboles UTF8 que je veux! 

p.s. Mon champ de table MySQL est du type "LongText". Cependant, lorsque j'ai généré automatiquement les mappages de champs à l'aide du logiciel MyGeneration, le type de champ était automatiquement défini sur MySqlDbType.Blob en C #. 

Fait intéressant, j'utilise le type MySqlDbType.Blob avec des caractères UTF8 depuis plusieurs mois sans problème, jusqu'au jour où j'ai essayé d'écrire une chaîne contenant des caractères spécifiques.

J'espère que cela aidera quelqu'un qui a du mal à trouver la raison de l'erreur. 

2

Pour corriger cette erreur, j'ai mis à niveau ma base de données MySQL vers utf8mb4, qui prend en charge l'intégralité du jeu de caractères Unicode en suivant ce tutoriel détaillé . Je suggère de l'examiner avec soin, car il y a pas mal de pièges (par exemple, les clés d'index peuvent devenir trop volumineuses en raison des nouveaux encodages après lesquels vous devez modifier les types de champs).

1
metakermit

Bonjour, j’ai aussi eu cette erreur lorsque j’utilise mes bases de données en ligne à partir du serveur GoDaddy Je pense qu’il a la version mysql de 5.1 ou plus. mais quand je fais de mon serveur localhost (version 5.7) il était bien après que j'ai créé la table du serveur local et copié sur le serveur en ligne en utilisant mysql yog je pense que le problème est avec le jeu de caractères

Capture d'écran ici

1
Hashain Lakshan

J'ai ajouté binaire avant le nom de la colonne et résoudre l'erreur de jeu de caractères.

insérer dans les valeurs de la table (chaîne binaire nom_colonne 1);

1
Richardhe2007

La solution pour moi lors de l'exécution de cette valeur de chaîne incorrecte: '\ xF8' pour une erreur de colonne à l'aide de scriptcase était de m'assurer que ma base de données est configurée pour utf8 general ci et que sont donc mes collations de champs. Ensuite, lorsque je fais l'importation des données d'un fichier csv, je le charge dans UE Studio, puis je l'enregistre au format utf8 et voilà. Cela fonctionne comme un charme, 29000 enregistrements dedans aucune erreur. Auparavant, j'essayais d'importer un fichier csv créé par Excel. 

1
mainebrain

Il y a de bonnes réponses ici. J'ajoute simplement le mien depuis que j'ai rencontré la même erreur, mais le problème s'est avéré complètement différent. (Peut-être à la surface la même chose, mais une cause fondamentale différente.)

Pour moi l'erreur est survenue pour le champ suivant:

@Column(nullable = false, columnDefinition = "VARCHAR(255)")
private URI consulUri;

Cela finit par être stocké dans la base de données en tant que sérialisation binaire de la classe URI. Cela n'a soulevé aucun drapeau avec les tests unitaires (avec H2) ou les tests CI/d'intégration (avec MariaDB4j ), cela a explosé dans notre configuration de production. (Même si, une fois le problème compris, il était assez facile de voir la mauvaise valeur dans l'instance MariaDB4j; le test n'a pas été annulé.) La solution a été de créer un mappeur de type personnalisé:

package redacted;

import javax.persistence.AttributeConverter;
import Java.net.URI;
import Java.net.URISyntaxException;

import static Java.lang.String.format;

public class UriConverter implements AttributeConverter<URI, String> {
    @Override
    public String convertToDatabaseColumn(URI attribute) {
        return attribute.toString();
    }

    @Override
    public URI convertToEntityAttribute(String field) {
        try {
            return new URI(field);
        }
        catch (URISyntaxException e) {
            throw new RuntimeException(format("could not convert database field to URI: %s", field));
        }
    }
}

Utilisé comme suit:

@Column(nullable = false, columnDefinition = "VARCHAR(255)")
@Convert(converter = UriConverter.class)
private URI consulUri;

En ce qui concerne Hibernate, il semble disposer de nombreux mappeurs de types fournis , y compris pour Java.net.URL, mais pas pour Java.net.URI (ce dont nous avions besoin ici).

0
Sander Verhagen

Dans mon cas, Incorrect string value: '\xCC\x88'..., le problème était qu'un o-umlaut était dans son état décomposé. Cette question-réponse m'a aidé à comprendre la différence entre et ö. En PHP, le correctif pour moi était d'utiliser la bibliothèque du normaliseur PHP . Par exemple, Normalizer::normalize('o¨', Normalizer::FORM_C).

0
MM.

J'ai essayé presque toutes les étapes mentionnées ici. Aucun n'a travaillé. Téléchargé mariadb. Ça a marché. Je sais que ce n’est pas une solution mais que cela pourrait aider quelqu'un à identifier le problème rapidement ou à donner une solution temporaire.

Server version: 10.2.10-MariaDB - MariaDB Server
Protocol version: 10
Server charset: UTF-8 Unicode (utf8)
0
cherankrish

Dans mon cas, ce problème a été résolu en changeant le codage de la colonne Mysql en "binaire" (le type de données sera automatiquement changé en VARBINARY). Je ne pourrai probablement pas filtrer ni chercher dans cette colonne, mais je n'en ai pas besoin.

0
WilyDen

Ce que j’ai fait, c’est d’abord modifié le type de colonne en LONG BLOB, inséré des données, puis modifié le type de colonne en VARCHAR (255), car les données n’étaient pas très sensibles. Je suggère que vous puissiez essayer ceci si seulement vous ne disposez pas de données que vous ne voulez pas déformer.

0
Shubh Dixit

Dans mon cas, j'ai d'abord rencontré un '???' dans mon site Web, alors je vérifie le jeu de caractères de Mysql qui est latin maintenant, donc je le change en utf-8, puis je redémarre mon projet, puis j'ai la même erreur avec vous, puis j'ai trouvé que j'oublie de changer le jeu de caractères de la base et changez en utf-8, boum, ça a marché.

0
acoder2013