"Неправильное строковое значение" при попытке вставить UTF-8 в MySQL через JDBC?

Это как мой подключения:
Connection conn = DriverManager.getConnection(url + dbName + "?useUnicode=true&characterEncoding=utf-8", userName, password);

и я получаю следующую ошибку при tyring, чтобы добавить строку в таблицу:
Incorrect string value: 'xF0x90x8Dx83xF0x90...' for column 'content' at row 1

я вставляю тысячи записей, и я всегда получаю эту ошибку, когда текст содержит xF0 (т. е. неправильное строковое значение всегда начинается с xF0).

параметры сортировки столбца-utf8_general_ci.

в чем может быть проблема?

12 ответов


в MySQL utf8 разрешает только символы Юникода, которые могут быть представлены с 3 байтами в UTF-8. Здесь у вас есть символ, который требует 4 байта: \xF0\x90\x8D\x83 (U+10343 ГОТИЧЕСКАЯ БУКВА SAUIL).

если у вас есть MySQL 5.5 или позже, вы можете изменить кодировку столбца от utf8 до utf8mb4. Эта кодировка позволяет хранить символы, занимающие 4 байта в UTF-8.

возможно, Вам также придется установить свойство сервера character_set_server в utf8mb4 в файле конфигурации MySQL. Кажется, что Connector / J по умолчанию 3-байтовый Unicode в противном случае:

например, чтобы использовать 4-байтовые наборы символов UTF-8 С Connector / J, настройте сервер MySQL с character_set_server=utf8mb4 и оставить characterEncoding из строки подключения Connector/J. Затем Connector / J автоматически установит параметр UTF-8.


строки, содержащие \xF0 просто символы, закодированные как несколько байтов использование UTF-8.

хотя ваши параметры сортировки установлены в utf8_general_ci, я подозреваю, что кодировка символов базы данных, таблицы или даже столбца может отличаться. Они независимые настройки. Попробуйте:

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

замените любой ваш фактический тип данных для VARCHAR (255)


получил ту же проблему, чтобы сохранить данные с utf8mb4 должен убедиться, что:

  1. character_set_client, character_set_connection, character_set_results are utf8mb4: character_set_client и character_set_connection укажите набор символов, в котором операторы отправляются клиентом,character_set_results указывает набор символов, в котором сервер возвращает клиенту результаты запроса.
    См.кодировка-соединение.

  2. кодировка таблицы и столбца utf8mb4

для JDBC существует два решения:

Решение 1 (необходимо перезапустить MySQL):

  1. изменить my.cnf как следующее и перезапустите MySQL:

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

это может убедиться, что база данных и character_set_client, character_set_connection, character_set_results are utf8mb4 по умолчанию.

  1. перезапустить MySQL

  2. измените кодировку таблицы и столбца на utf8mb4

  3. прекратите указывать characterEncoding=UTF-8 и characterSetResults=UTF-8 в соединителе jdbc, потому что это переопределит character_set_client, character_set_connection, character_set_results to utf8

решение два (не нужно перезапускать MySQL):

  1. измените кодировку таблицы и столбца на utf8mb4

  2. задание characterEncoding=UTF-8 в соединителе jdbc, потому что соединитель jdbc не поддерживает utf8mb4.

  3. напишите свой SQL statment так (нужно добавить allowMultiQueries=true к разъему jdbc):

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

это будет убедиться, что каждое соединение с сервером,character_set_client,character_set_connection,character_set_results are utf8mb4.
Также смотрите кодировка-соединение.


я хотел объединить несколько сообщений, чтобы сделать полный ответ на это, так как это, похоже, несколько шагов.

  1. выше советы @madtracey

/etc/mysql/my.cnf или /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

опять же из Совета прежде всего JDBC соединения имели characterEncoding=UTF-8и characterSetResults=UTF-8 удалены от них

С этим набором -Dfile.encoding=UTF-8 казалось, не имело никакого значения.

я все еще не мог написать международный текст в получение БД тот же провал, что и выше

теперь используя этот как-преобразовать-весь-mysql-база данных-набор символов-и-параметры сортировки-в-utf-8

обновите всю свою БД для использования utf8mb4

ALTER DATABASE YOURDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

запустите этот запрос, который дает вам то, что нужно выполнить

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%')

копировать вставить вывод в Редакторе заменить все / ни с чем post обратно в mysql при подключении к правильной БД.

это все, что надо было сделать и все, кажется, работает для мне. Не -Dfile.encoding=UTF-8 не включен и, похоже, работает так, как ожидалось

у E2A все еще есть проблема ? Я, конечно, в производстве, поэтому оказывается, вам нужно проверить, что было сделано выше, так как это иногда не работает, вот причина и исправить в этом сценарии:

show create table user

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

вы можете видеть, что некоторые из них все еще латинские попытка вручную обновить запись:

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

так давайте сузим его вниз:

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)

короче говоря, мне пришлось уменьшить размер этого поля, чтобы заставить обновление работать.

теперь, когда я запускаю:

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

все работает


В моем случае, я пробовал все выше, ничего не получалось. Я уверен, что моя база данных выглядит ниже.

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

Connection id:      12
Current database:   xxx
Current user:       yo@localhost
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

Итак, я ищу кодировку столбцов в каждой таблице

show create table company;

оказывается, кодировка столбца Латинская. Вот почему я не могу вставить в базу данных.

 ALTER TABLE company CONVERT TO CHARACTER SET utf8;

это может вам помочь. :)


просто делать

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 ;

у меня была эта проблема с моим приложением PLAY Java. Это моя трассировка стека для этого исключения:

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.$anonfun$applyOrElse(Routes.scala:690)
  at play.core.routing.HandlerInvokerFactory$$anon.resultCall(HandlerInvoker.scala:134)
  at play.core.routing.HandlerInvokerFactory$$anon.resultCall(HandlerInvoker.scala:133)
  at play.core.routing.HandlerInvokerFactory$JavaActionInvokerFactory$$anon$$anon$$anon.invocation(HandlerInvoker.scala:108)
  at play.core.j.JavaAction$$anon.call(JavaAction.scala:88)
  at play.http.DefaultActionCreator.call(DefaultActionCreator.java:31)
  at play.core.j.JavaAction.$anonfun$apply(JavaAction.scala:138)
  at scala.concurrent.Future$.$anonfun$apply(Future.scala:655)
  at scala.util.Success.$anonfun$map(Try.scala:251)
  at scala.util.Success.map(Try.scala:209)
  at scala.concurrent.Future.$anonfun$map(Future.scala:289)
  at scala.concurrent.impl.Promise.liftedTree1(Promise.scala:29)
  at scala.concurrent.impl.Promise.$anonfun$transform(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.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(Action.scala:96)
  at scala.concurrent.Future.$anonfun$flatMap(Future.scala:304)
  at scala.concurrent.impl.Promise.$anonfun$transformWith(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(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

Я пытался сохранить запись с помощью ввода-вывода.Ebean. Я исправил это, создав свою базу данных с помощью параметров сортировки utf8mb4, и применил эволюцию воспроизведения для создания всех таблиц, чтобы все таблицы были воссозданы с помощью параметров сортировки utf-8.

CREATE DATABASE inventory CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

его в основном вызвано из-за некоторых символов Юникода. В моем случае это был символ рупии.

чтобы быстро исправить это, я должен был определить символ, вызывающий эту ошибку. Я скопировал весь текст в текстовый редактор, такой как vi, и заменил тревожный символ текстовым.


у меня была такая же проблема в моем проекте рельсов:

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

Решение 1: перед сохранением в БД преобразовать строку в base64 с помощью Base64.encode64(subject) и после извлечения из БД используйте Base64.decode64(subject)

решение 2:

Шаг 1: Измените набор символов (и параметры сортировки) для столбца subject на

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

Шаг 2: в базе.в формате YML использовать

encoding :utf8mb4

мое решение-изменить тип столбца с varchar (255) на blob


I вы хотите применить изменение только для одного поля, вы можете попробовать сериализовать поле

class MyModel < ActiveRecord::Base
  serialize :content

  attr_accessible :content, :title
end

чтобы решить эту ошибку, выполните следующие действия:

  1. phpMyAdmin и
  2. your_table
  3. вкладка"структура"
  4. измените параметры сортировки вашего поля с latin1_swedish_ci (или что бы это ни было) до utf8_general_ci