web-dev-qa-db-de.com

"Falscher String-Wert" beim Versuch, UTF-8 über JDBC in MySQL einzufügen?

So wird meine Verbindung eingerichtet:
Connection conn = DriverManager.getConnection(url + dbName + "?useUnicode=true&characterEncoding=utf-8", userName, password);

Und ich erhalte die folgende Fehlermeldung, wenn ich versuche, einer Tabelle eine Zeile hinzuzufügen:
Incorrect string value: '\xF0\x90\x8D\x83\xF0\x90...' for column 'content' at row 1

Ich füge Tausende von Datensätzen ein und erhalte immer dann diesen Fehler, wenn der Text\xF0 enthält (d. H. Der falsche Zeichenfolgenwert beginnt immer mit\xF0).

Die Kollatierung der Spalte lautet utf8_general_ci.

Woran könnte das liegen?

185
Lior

MySQL's utf8 erlaubt nur die Unicode-Zeichen, die in UTF-8 mit 3 Bytes dargestellt werden können. Hier haben Sie ein Zeichen, das 4 Bytes benötigt:\xF0\x90\x8D\x83 ( + 10343 GOTHIC LETTER SAUIL ).

Wenn Sie MySQL 5.5 oder neuer haben, können Sie die Spaltenkodierung von utf8 bis utf8mb4 . Diese Codierung ermöglicht die Speicherung von Zeichen, die 4 Byte in UTF-8 belegen.

Möglicherweise müssen Sie auch die Servereigenschaft character_set_server bis utf8mb4 in der MySQL-Konfigurationsdatei. Es scheint, dass Connector/J ist ansonsten standardmäßig 3-Byte-Unicode :

Um beispielsweise 4-Byte-UTF-8-Zeichensätze mit Connector/J zu verwenden, konfigurieren Sie den MySQL-Server mit character_set_server=utf8mb4, und lassen Sie characterEncoding aus der Connector/J-Verbindungszeichenfolge. Connector/J erkennt dann automatisch die UTF-8-Einstellung.

274
Joni

Die Zeichenfolgen, die \xF0 Enthalten, sind einfach Zeichen, die als mehrere Bytes codiert sind unter Verwendung von UTF-8.

Obwohl Ihre Kollatierung auf utf8_general_ci festgelegt ist, vermute ich, dass die Zeichenkodierung der Datenbank, Tabelle oder sogar Spalte unterschiedlich sein kann. Sie sind nabhängige Einstellungen . Versuchen:

ALTER TABLE database.table MODIFY COLUMN col VARCHAR(255)  
    CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;

Ersetzen Sie VARCHAR (255) durch Ihren tatsächlichen Datentyp.

80
Eric J.

Habe das gleiche Problem, um die Daten mit utf8mb4 Zu speichern, muss folgendes sichergestellt werden:

  1. character_set_client, character_set_connection, character_set_results Sind utf8mb4: character_set_client Und character_set_connection Geben den Zeichensatz an, in dem Anweisungen vom Client gesendet werden, character_set_results Den Zeichensatz in dem der Server Abfrageergebnisse an den Client zurückgibt.
    Siehe Zeichensatzverbindung .

  2. die Tabellen- und Spaltencodierung ist utf8mb4

Für JDBC gibt es zwei Lösungen:

Lösung 1 (muss MySQL neu starten):

  1. ändere my.cnf wie folgt und starte MySQL neu:

    [mysql]
    default-character-set=utf8mb4
    
    [mysqld]
    character-set-server=utf8mb4
    collation-server=utf8mb4_unicode_ci
    

dies kann sicherstellen, dass die Datenbank und character_set_client, character_set_connection, character_set_results standardmäßig utf8mb4 sind.

  1. starten Sie MySQL neu

  2. ändern Sie die Tabellen- und Spaltencodierung in utf8mb4

  3. STOPPEN Sie die Angabe von characterEncoding=UTF-8 Und characterSetResults=UTF-8 Im jdbc-Connector, da dies character_set_client, character_set_connection, character_set_results Zu utf8

Lösung 2 (Sie müssen MySQL nicht neu starten):

  1. ändern Sie die Tabellen- und Spaltencodierung in utf8mb4

  2. wenn Sie characterEncoding=UTF-8 im JDBC-Connector angeben, wird utf8mb4 vom JDBC-Connector nicht unterstützt.

  3. schreiben Sie Ihre SQL-Anweisung wie folgt (Sie müssen allowMultiQueries=true zum JDBC-Connector hinzufügen):

    'SET NAMES utf8mb4;INSERT INTO Mytable ...';
    

dadurch wird sichergestellt, dass jede Verbindung zum Server character_set_client,character_set_connection,character_set_resultsutf8mb4 ist.
Siehe auch Zeichensatzverbindung .

47
madtracy

Ich wollte ein paar Posts zusammenfassen, um eine vollständige Antwort darauf zu finden, da es anscheinend nur ein paar Schritte sind.

  1. Oben genannter Rat von @madtracey

/etc/mysql/my.cnf Oder /etc/mysql/mysql.conf.d/mysqld.cnf

[mysql]
default-character-set=utf8mb4

[mysqld_safe]
socket          = /var/run/mysqld/mysqld.sock
Nice            = 0

[mysqld]
##
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

Nochmals, vor allem aus den Ratschlägen von jdbc-Verbindungen wurden characterEncoding=UTF-8 Und characterSetResults=UTF-8 Entfernt

Mit diesem Set schien -Dfile.encoding=UTF-8 Keinen Unterschied zu machen.

Ich konnte immer noch keinen internationalen Text in db schreiben, der den gleichen Fehler wie oben hatte

Verwenden Sie jetzt diese wie-konvertiert-man-einen-gesamten-mysql-Datenbank-Zeichensatz-und-Kollatierung-zu-utf-8

Aktualisieren Sie Ihre gesamte Datenbank, um utf8mb4 Zu verwenden.

ALTER DATABASE YOURDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Führen Sie diese Abfrage aus, die angibt, was angerufen werden muss

SELECT CONCAT(
'ALTER TABLE ',  table_name, ' CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;  ', 
'ALTER TABLE ',  table_name, ' CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;  ')
FROM information_schema.TABLES AS T, information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` AS C
WHERE C.collation_name = T.table_collation
AND T.table_schema = 'YOURDB'
AND
(C.CHARACTER_SET_NAME != 'utf8mb4'
    OR
 C.COLLATION_NAME not like 'utf8mb4%')

Kopieren Einfügen Ausgabe im Editor Alle ersetzen | mit nichts zurück in MySQL posten, wenn verbunden, um DB zu korrigieren.

Das war alles, was getan werden musste und alles scheint für mich zu funktionieren. Nicht das - Dfile.encoding=UTF-8 Ist nicht aktiviert und es scheint wie erwartet zu funktionieren

E2A Haben Sie immer noch ein Problem? Ich bin mit Sicherheit in der Produktion, daher müssen Sie überprüfen, was oben gemacht wurde, da dies manchmal der Fall ist funktioniert nicht, hier ist Grund und Fehlerbehebung in diesem Szenario:

show create table user

  `password` varchar(255) CHARACTER SET latin1 NOT NULL,
  `username` varchar(255) CHARACTER SET latin1 NOT NULL,

Einige Lateinamerikaner versuchen immer noch, den Datensatz manuell zu aktualisieren:

ALTER TABLE user CONVERT TO CHARACTER SET utf8mb4;
ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes

Also lassen Sie es uns eingrenzen:

mysql> ALTER TABLE user change username username varchar(255) CHARACTER SET utf8mb4 not NULL;
ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes
mysql> ALTER TABLE user change username username varchar(100) CHARACTER SET utf8mb4 not NULL;
Query OK, 5 rows affected (0.01 sec)

Kurz gesagt, ich musste das Feld verkleinern, damit das Update funktioniert.

Wenn ich jetzt renne:

mysql> ALTER TABLE user CONVERT TO CHARACTER SET utf8mb4;
Query OK, 5 rows affected (0.01 sec)
Records: 5  Duplicates: 0  Warnings: 0

Es funktioniert alles

10
Vahid

In meinem Fall habe ich alles versucht, nichts hat funktioniert. Ich bin mir ziemlich sicher, meine Datenbank sieht wie folgt aus.

mysql  Ver 14.14 Distrib 5.7.17, for Linux (x86_64) using  EditLine wrapper

Connection id:      12
Current database:   xxx
Current user:       [email protected]
SSL:            Not in use
Current pager:      stdout
Using outfile:      ''
Using delimiter:    ;
Server version:     5.7.17-0ubuntu0.16.04.1 (Ubuntu)
Protocol version:   10
Connection:     Localhost via UNIX socket
Server characterset:    utf8
Db     characterset:    utf8
Client characterset:    utf8
Conn.  characterset:    utf8
UNIX socket:        /var/run/mysqld/mysqld.sock
Uptime:         42 min 49 sec

Threads: 1  Questions: 372  Slow queries: 0  Opens: 166  Flush tables: 1  Open tables: 30  Queries per second avg: 0.144

deshalb schaue ich in jeder Tabelle nach dem Zeichensatz der Spalten

show create table company;

Es stellt sich heraus, dass der Zeichensatz der Spalte lateinisch ist. Deshalb kann ich kein Chinesisch in die Datenbank einfügen.

 ALTER TABLE company CONVERT TO CHARACTER SET utf8;

Das könnte dir helfen. :)

5
crazy_phage

Angenommen, Sie verwenden phpmyadmin, um diesen Fehler zu beheben, gehen Sie folgendermaßen vor:

  1. phpMyAdmin
  2. your_table
  3. "Registerkarte Struktur"
  4. ändern Sie die Sortierung Ihres Feldes von latin1_swedish_ci (oder was auch immer es ist) zu utf8_general_ci
5
Teo Mihaila

mach einfach

ALTER TABLE `some_table` 
CHARACTER SET = utf8 , COLLATE = utf8_general_ci ;

ALTER TABLE `some_table` 
CHANGE COLUMN `description_with_latin_or_something` `description` TEXT CHARACTER SET 'utf8' NOT NULL ;
4
shareef

Ich hatte dieses Problem mit meiner Anwendung PLAY Java). Dies ist mein Stack-Trace für diese Ausnahme:

javax.persistence.PersistenceException: Error[Incorrect string value: '\xE0\xA6\xAC\xE0\xA6\xBE...' for column 'product_name' at row 1]
  at io.ebean.config.dbplatform.SqlCodeTranslator.translate(SqlCodeTranslator.Java:52)
  at io.ebean.config.dbplatform.DatabasePlatform.translate(DatabasePlatform.Java:192)
  at io.ebeaninternal.server.persist.dml.DmlBeanPersister.execute(DmlBeanPersister.Java:83)
  at io.ebeaninternal.server.persist.dml.DmlBeanPersister.insert(DmlBeanPersister.Java:49)
  at io.ebeaninternal.server.core.PersistRequestBean.executeInsert(PersistRequestBean.Java:1136)
  at io.ebeaninternal.server.core.PersistRequestBean.executeNow(PersistRequestBean.Java:723)
  at io.ebeaninternal.server.core.PersistRequestBean.executeNoBatch(PersistRequestBean.Java:778)
  at io.ebeaninternal.server.core.PersistRequestBean.executeOrQueue(PersistRequestBean.Java:769)
  at io.ebeaninternal.server.persist.DefaultPersister.insert(DefaultPersister.Java:456)
  at io.ebeaninternal.server.persist.DefaultPersister.insert(DefaultPersister.Java:406)
  at io.ebeaninternal.server.persist.DefaultPersister.save(DefaultPersister.Java:393)
  at io.ebeaninternal.server.core.DefaultServer.save(DefaultServer.Java:1602)
  at io.ebeaninternal.server.core.DefaultServer.save(DefaultServer.Java:1594)
  at io.ebean.Model.save(Model.Java:190)
  at models.Product.create(Product.Java:147)
  at controllers.PushData.xlsupload(PushData.Java:67)
  at router.Routes$$anonfun$routes$1.$anonfun$applyOrElse$40(Routes.scala:690)
  at play.core.routing.HandlerInvokerFactory$$anon$3.resultCall(HandlerInvoker.scala:134)
  at play.core.routing.HandlerInvokerFactory$$anon$3.resultCall(HandlerInvoker.scala:133)
  at play.core.routing.HandlerInvokerFactory$JavaActionInvokerFactory$$anon$8$$anon$2$$anon$1.invocation(HandlerInvoker.scala:108)
  at play.core.j.JavaAction$$anon$1.call(JavaAction.scala:88)
  at play.http.DefaultActionCreator$1.call(DefaultActionCreator.Java:31)
  at play.core.j.JavaAction.$anonfun$apply$8(JavaAction.scala:138)
  at scala.concurrent.Future$.$anonfun$apply$1(Future.scala:655)
  at scala.util.Success.$anonfun$map$1(Try.scala:251)
  at scala.util.Success.map(Try.scala:209)
  at scala.concurrent.Future.$anonfun$map$1(Future.scala:289)
  at scala.concurrent.impl.Promise.liftedTree1$1(Promise.scala:29)
  at scala.concurrent.impl.Promise.$anonfun$transform$1(Promise.scala:29)
  at scala.concurrent.impl.CallbackRunnable.run$$$capture(Promise.scala:60)
  at scala.concurrent.impl.CallbackRunnable.run(Promise.scala)
  at play.core.j.HttpExecutionContext$$anon$2.run(HttpExecutionContext.scala:56)
  at play.api.libs.streams.Execution$trampoline$.execute(Execution.scala:70)
  at play.core.j.HttpExecutionContext.execute(HttpExecutionContext.scala:48)
  at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:68)
  at scala.concurrent.impl.Promise$KeptPromise$Kept.onComplete(Promise.scala:368)
  at scala.concurrent.impl.Promise$KeptPromise$Kept.onComplete$(Promise.scala:367)
  at scala.concurrent.impl.Promise$KeptPromise$Successful.onComplete(Promise.scala:375)
  at scala.concurrent.impl.Promise.transform(Promise.scala:29)
  at scala.concurrent.impl.Promise.transform$(Promise.scala:27)
  at scala.concurrent.impl.Promise$KeptPromise$Successful.transform(Promise.scala:375)
  at scala.concurrent.Future.map(Future.scala:289)
  at scala.concurrent.Future.map$(Future.scala:289)
  at scala.concurrent.impl.Promise$KeptPromise$Successful.map(Promise.scala:375)
  at scala.concurrent.Future$.apply(Future.scala:655)
  at play.core.j.JavaAction.apply(JavaAction.scala:138)
  at play.api.mvc.Action.$anonfun$apply$2(Action.scala:96)
  at scala.concurrent.Future.$anonfun$flatMap$1(Future.scala:304)
  at scala.concurrent.impl.Promise.$anonfun$transformWith$1(Promise.scala:37)
  at scala.concurrent.impl.CallbackRunnable.run$$$capture(Promise.scala:60)
  at scala.concurrent.impl.CallbackRunnable.run(Promise.scala)
  at akka.dispatch.BatchingExecutor$AbstractBatch.processBatch(BatchingExecutor.scala:55)
  at akka.dispatch.BatchingExecutor$BlockableBatch.$anonfun$run$1(BatchingExecutor.scala:91)
  at scala.runtime.Java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.Java:12)
  at scala.concurrent.BlockContext$.withBlockContext(BlockContext.scala:81)
  at akka.dispatch.BatchingExecutor$BlockableBatch.run(BatchingExecutor.scala:91)
  at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:40)
  at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(ForkJoinExecutorConfigurator.scala:43)
  at akka.dispatch.forkjoin.ForkJoinTask.doExec(ForkJoinTask.Java:260)
  at akka.dispatch.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.Java:1339)
  at akka.dispatch.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.Java:1979)
  at akka.dispatch.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.Java:107)
Caused by: Java.sql.SQLException: Incorrect string value: '\xE0\xA6\xAC\xE0\xA6\xBE...' for column 'product_name' at row 1
  at com.mysql.jdbc.SQLError.createSQLException(SQLError.Java:1074)
  at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.Java:4096)
  at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.Java:4028)
  at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.Java:2490)
  at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.Java:2651)
  at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.Java:2734)
  at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.Java:2155)
  at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.Java:2458)
  at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.Java:2375)
  at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.Java:2359)
  at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.Java:61)
  at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.Java)
  at io.ebeaninternal.server.type.DataBind.executeUpdate(DataBind.Java:82)
  at io.ebeaninternal.server.persist.dml.InsertHandler.execute(InsertHandler.Java:122)
  at io.ebeaninternal.server.persist.dml.DmlBeanPersister.execute(DmlBeanPersister.Java:73)
  ... 59 more

Ich habe versucht, einen Datensatz mit io.Ebean zu speichern. Ich habe es behoben, indem ich meine Datenbank mit der Kollatierung utf8mb4 neu erstellt habe, und Play Evolution angewendet, um alle Tabellen neu zu erstellen, sodass alle Tabellen mit der Kollatierung utf-8 neu erstellt werden sollten.

CREATE DATABASE inventory CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
3

Ich hatte das gleiche Problem in meinem Rails Projekt:

Incorrect string value: '\xF0\xA9\xB8\xBDs ...' for column 'subject' at row1

Lösung 1: vor dem Speichern in db konvertieren Sie den String mit Base64.encode64(subject) in base64 und nach dem Abrufen von db verwenden Sie Base64.decode64(subject)

Lösung 2:

Schritt 1: Ändern Sie den Zeichensatz (und die Sortierung) für die Betreffspalte um

ALTER TABLE t1 MODIFY
subject VARCHAR(255)
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci;

Schritt 2: In database.yml verwenden

encoding :utf8mb4
3
ravi

Es ist hauptsächlich auf einige Unicode-Zeichen zurückzuführen. In meinem Fall war es das Rupien-Währungssymbol.

Um dies schnell zu beheben, musste ich den Charakter finden, der diesen Fehler verursacht hat. Ich habe den gesamten Text in einen Texteditor wie vi kopiert und das störende Zeichen durch einen Text ersetzt.

3
BTR Naidu

Wenn Sie die Änderung nur für ein Feld anwenden möchten, können Sie versuchen, das Feld zu serialisieren

class MyModel < ActiveRecord::Base
  serialize :content

  attr_accessible :content, :title
end
2
Paul Marclay

Sie müssen utf8mb4 in Meta-HTML und auch in Ihrem Server einstellen, ändern Sie die Tabelle und setzen Sie die Sortierung auf utf8mb4

1
Sona Israyelyan

Wenn Sie eine neue MySQL-Tabelle erstellen, können Sie den Zeichensatz aller Spalten bei der Erstellung angeben. Dies hat das Problem für mich behoben.

CREATE TABLE tablename (
<list-of-columns>
)
CHARSET SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Sie können weitere Details lesen: https://dev.mysql.com/doc/refman/8.0/en/charset-column.html

1
amucunguzi

meine Lösung besteht darin, den Spaltentyp von varchar (255) in blob zu ändern

1
zhuochen shen

dies ist nicht die Empfehlung Lösung. Aber es lohnt sich zu teilen. Seit meinem Projekt werden die DBMS von alten Mysql auf neueste (8) aktualisiert. Aber ich kann die Tabellenstruktur nicht ändern, nur die DBMS-Konfiguration (MySQL). Die Lösung für MySQL Server.

test on Windows mysql 8.0.15 on mysql config suche nach

sql-mode = "....."

kommentiere es aus. Oder in meinem Fall einfach eingeben/hinzufügen

sql-mode = "NO_ENGINE_SUBSTITUTION"

warum nicht empfohlene Lösung. denn wenn du latin1 verwendest (mein fall) .. füge die daten erfolgreich ein aber nicht den inhalt (mysql antwortet nicht mit fehler !!). Sie geben beispielsweise Informationen wie diese ein

bla\x12

es retten

bla [] (box)

okay .. für mein problem .. ich kann das feld auf UTF8 ändern .. aber es gibt ein kleines problem .. siehe obige antwort über andere lösung ist fehlgeschlagen da das wort nicht eingefügt wird weil es mehr als 2 bytes enthält (cmiiw) .. diese Lösung machen Sie Ihre Einfügedaten werden Box. Das vernünftige ist, Blob zu verwenden .. und Sie können meine Antwort überspringen.

Ein weiterer diesbezüglicher Test war die Verwendung von tf8_encode in Ihrem Code vor dem Speichern. Ich benutze auf latin1 und es war Erfolg (ich benutze nicht sql-mode)! Wie oben, antworte mit base64_encode.

Mein Vorschlag zur Analyse Ihrer Tabellenanforderung und der Versuch, von einem anderen Format zu UTF8 zu wechseln

0
user2905554