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

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

Вот как мое соединение установлено:
Connection conn = DriverManager.getConnection(url + dbName + "?useUnicode=true&characterEncoding=utf-8", userName, password);

И я получаю следующую ошибку, когда tyring добавляет строку в таблицу:
Incorrect string value: '\xF0\x90\x8D\x83\xF0\x90...' for column 'content' at row 1

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

Сопоставление столбцов - utf8_general_ci.

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

4b9b3361

Ответ 1

MySQL utf8 разрешает только символы Юникода, которые могут быть представлены с 3 байтами в UTF-8. Здесь у вас есть символ, которому нужно 4 байта:\xF0\x90\x8D\x83 (U + 10343 GOTHIC LETTER SAUIL).

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

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

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

Ответ 2

Строки, содержащие \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)

Ответ 3

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

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

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

Для JDBC есть два решения:

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

  1. измените my.cnf как 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 по умолчанию utf8mb4.

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

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

  3. ОСТАНОВИТЕ указание characterEncoding=UTF-8 и characterSetResults=UTF-8 в коннекторе jdbc, потому что это переопределит character_set_client, character_set_connection, character_set_results на utf8

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

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

  2. указание characterEncoding=UTF-8 utf8mb4 characterEncoding=UTF-8 в соединителе jdbc, так как соединитель jdbc не utf8mb4.

  3. напишите свой SQL-отчет следующим образом (необходимо добавить allowMultiQueries=true в соединитель jdbc):

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

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

Ответ 4

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

  • Выше совета @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 оказалось, что не имеет значения.

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

Теперь, используя этот метод" все-в-все-mysql-database-characterset-and-collation-to-utf-8

Обновите все свои db, чтобы использовать 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%')

Копировать вставку в редакторе заменить все | ничто не возвращается в mysql при подключении к правильному db.

Это все, что нужно было сделать, и все, похоже, работает на меня. Не - 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

Все работает

Ответ 5

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

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

поэтому я просматриваю колонку символов в каждой таблице

show create table company;

Оказывается, кодировка столбца является латинской. Поэтому я не могу вставить китайский в базу данных.

 ALTER TABLE company CONVERT TO CHARACTER SET utf8;

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

Ответ 6

просто

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 ;

Ответ 7

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

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

Ответ 8

В основном это связано с некоторыми символами юникода. В моем случае это был символ валюты Рупии.

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

Ответ 9

У меня была такая же проблема в моем проекте rails:

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

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

Решение 2:

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

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

Шаг 2: В database.yml используйте

encoding :utf8mb4

Ответ 10

У меня была эта проблема с моим приложением 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$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

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

CREATE DATABASE inventory CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Ответ 11

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

class MyModel < ActiveRecord::Base
  serialize :content

  attr_accessible :content, :title
end

Ответ 12

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

Ответ 13

Вам нужно установить utf8mb4 в мета-html, а также на вашем сервере изменить таблицу и установить параметры сортировки в utf8mb4

Ответ 14

Если вы создаете новую таблицу MySQL, вы можете указать кодировку всех столбцов при создании, и это решило проблему для меня.

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

Вы можете прочитать более подробную информацию: https://dev.mysql.com/doc/refman/8.0/en/charset-column.html

Ответ 15

это не решение рекомендации.. Но стоит поделиться. Так как мой проект - это обновление СУБД от старого Mysql до новейшего (8). Но я не могу изменить структуру таблицы, только конфиг СУБД (mysql). Решение для сервера MySQL.

тест на Windows MySQL 8.0.15 на MySQL конфигурации поиска

SQL-режим = "....."

раскомментируйте это. Или в моем случае просто введите/добавить

SQL-режим = "NO_ENGINE_SUBSTITUTION"

почему не рекомендуется решение. потому что, если вы используете latin1 (мой случай).. данные вставляются успешно, но не содержимое (mysql не отвечает с ошибкой !!). например, вы вводите информацию, как это

бла\х12

это сохранить

бла [] (коробка)

хорошо.. для моей проблемы.. я могу изменить поле на UTF8.. Но есть небольшая проблема.. см. выше, ответ о другом решении не удался, потому что слово не вставлено, потому что содержит больше чем 2 байта (cmiiw).. это Решение сделать ваши данные вставки в поле. Разумно использовать blob.. и вы можете пропустить мой ответ.

Еще одно тестирование было связано с использованием utf8_encode в вашем коде перед сохранением. Я использую на latin1, и это был успех (я не использую sql-mode)! ответ выше, используя base64_encode.

Я предложил проанализировать ваши требования к таблице и попытался перейти с другого формата на UTF8.