web-dev-qa-db-fra.com

MySQL lance une erreur de valeur de chaîne incorrecte

J'essaie de stocker le Tweet suivant dans une colonne de texte long/utf8 charset/MySQL 5.5. base de données avec stockage MyISAM activé.

Nous avons également essayé les jeux de caractères utf8mb4, utf16, utf32 mais nous ne pouvons pas surmonter ce problème.

Tweet="@Dorable_Dimples: Okay enough of those #IfYouWereMines I'm getting dep
ressed. #foreveralone ?" lol yes

mysql> ALTER DATABASE foo CHARACTER SET utf8 COLLATE utf8_bin;

mysql> show variables like 'char%';
+--------------------------+-------------------------------------------+
| Variable_name | Value |
+--------------------------+-------------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /rdsdbbin/mysql-5.5.12.R1/share/charsets/ |

Incorrect string value: '\xF0\x9F\x98\x94\xE2\x80...' for column 'Tweet' at row 1

Unable to store Tweet "@Dorable_Dimples: Okay enough of those #IfYouWereM
ines I'm getting depressed. #foreveralone ?" lol yes
javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCExcept
ion: could not insert
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityMana
gerImpl.Java:1387)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityMana
gerImpl.Java:1315)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityMana
gerImpl.Java:1321)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityMana
gerImpl.Java:843)
at Java.util.TimerThread.mainLoop(Timer.Java:512)
at Java.util.TimerThread.run(Timer.Java:462)

at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(
SQLStateConverter.Java:140)
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.ja
va:128)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelpe
r.Java:66)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(Abstra
ctReturningDelegate.Java:64)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(Abstract
EntityPersister.Java:2345)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(Abstract
EntityPersister.Java:2852)
at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentity
InsertAction.Java:71)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.Java:273)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplica
te(AbstractSaveEventListener.Java:320)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(Abstract
SaveEventListener.Java:203)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(
AbstractSaveEventListener.Java:129)
at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(E
JB3PersistEventListener.Java:69)
at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(
DefaultPersistEventListener.Java:179)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultP
ersistEventListener.Java:135)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultP
ersistEventListener.Java:61)
at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.Java:808)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.Java:782)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.Java:786)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityMana
gerImpl.Java:837)
... 5 more
Caused by: Java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x94\xE2\x
80...' for column 'Tweet' at row 1
at com.mysql.jdbc.SQLError.createSQLException(SQLError.Java:1073)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.Java:3609)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.Java:3541)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.Java:2002)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.Java:2163)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.Java:2624)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.jav
a:2127)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.Java:
2427)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.Java:
2345)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.Java:
2330)
at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAnd
Extract(IdentityGenerator.Java:94)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(Abstra
ctReturningDelegate.Java:57)
36
priya

C'est le personnage à la fin du Tweet qui pose problème.

Il ressemble à un personnage 'emoji' aka un visage souriant japonais mais il ne s'affiche pas pour moi dans Chrome ou Safari.

Il existe des problèmes connus de stockage de caractères utf de 4 octets dans certaines versions de MySQL. Apparemment, vous devez utiliser utf8mb4 pour représenter des caractères UTF de 4 octets, car le jeu de caractères utf8 normal ne peut représenter que des caractères jusqu'à 3 octets et ne peut donc pas stocker de caractères qui se trouvent en dehors de Plan multilingue de base

http://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html

Ce qui est nouveau pour moi car cela signifie fondamentalement que le type de données utf8 dans MySQL n'est pas vraiment le bon utf8.

Il y a des suggestions sur la façon de gérer cela ici Comment insérer le caractère utf-8 mb4 (emoji dans ios5) dans mysql? y compris:

"Assurez-vous également que votre couche d'application définit le jeu de caractères de ses connexions à la base de données sur utf8mb4. Vérifiez que cela se produit réellement - si vous exécutez une ancienne version de la bibliothèque client mysql de votre framework choisi, elle n'a peut-être pas été compilée avec le support utf8mb4 et il ne définira pas le jeu de caractères correctement. Sinon, vous devrez peut-être le mettre à jour ou le compiler vous-même "

Si vous utilisez Connector/J, vous devez définir character_set_server = utf8mb4 dans la configuration de connexion.

Tous vos jeux de caractères devraient être utf8mb4, que vous avez peut-être essayé mais qui ne sont pas actuellement définis.

57
Danack

J'aime la réponse de Danask57 - c'est correct et la "bonne" façon de le faire. (J'ai voté moi-même)

Cependant, une autre solution rapide et sale consiste à modifier le schéma. utilisez un varbinary ou binary pour stocker la chaîne Tweet:

http://dev.mysql.com/doc/refman/5.0/en/binary-varbinary.html

L'avantage est que vous n'aurez aucun problème de jeu de caractères.

L'inconvénient est que la comparaison et le tri des chaînes seront perdus et que vous ne pourrez pas indexer le texte intégral de la colonne.

Juste une suggestion, mais ce n'est pas la "bonne" réponse, juste une solution rapide et sale qui fait fonctionner les choses.

8
FlipMcF

J'avais ce problème précis. Pour résoudre, changez l'encodage par défaut côté serveur mysql en utf8mb4 en suivant cet excellent guide: http://mathiasbynens.be/notes/mysql-utf8mb4 .

N'oubliez pas de redémarrer votre service mysqld après avoir apporté des modifications au fichier de configuration.

Pour moi, j'avais également besoin de mettre à jour le pilote mysql jdbc vers la version 5.1.18 (à partir de la version 5.1.6). J'ai lu quelque part que vous devez utiliser au moins la version 5.1.14 pour que le pilote mysql jdbc fonctionne correctement avec l'encodage de caractères utf8mb4. J'espère que cela t'aides!

5
mancini0

Pourquoi avez-vous du texte en dehors des guillemets dans votre exemple - c'est-à-dire "lol oui"

Tweet="@Dorable_Dimples: Okay enough of those #IfYouWereMines I'm getting depressed. #foreveralone ?" lol yes
1
Adrian Cornish