尝试通过JDBC将UTF-8插入到MySQL中时出现“错误的string值”?

这是我的连接设置:
Connection conn = DriverManager.getConnection(url + dbName + "?useUnicode=true&characterEncoding=utf-8", userName, password);

而且在向表中添加一行时出现以下错误:
Incorrect string value: '\xF0\x90\x8D\x83\xF0\x90...' for column 'content' at row 1

我插入了成千上万的logging,当文本包含\ xF0时(即不正确的string值始终以\ xF0开头),我总是得到这个错误。

该列的sorting规则是utf8_general_ci。

可能是什么问题呢?

MySQL的utf8只允许UTF-8中可以用3个字节表示的Unicode字符。 这里有一个需要4个字节的字符:\ xF0 \ x90 \ x8D \ x83( U + 10343 GOTHIC LETTER SAUIL )。

如果您有MySQL 5.5或更高版本,则可以将列编码从utf8更改为utf8mb4 。 该编码允许以UTF-8格式存储占用4个字节的字符。

您可能还必须在MySQLconfiguration文件中将服务器属性character_set_server设置为utf8mb4 。 看来连接器/ J默认为3字节的Unicode,否则 :

例如,要使用连接器/ J使用4字节的UTF-8字符集,请使用character_set_server=utf8mb4configurationMySQL服务器,并将characterEncoding保留为Connector / J连接string。 Connector / J将自动检测UTF-8设置。

包含\xF0的string只是使用UTF-8 编码为多个字节的字符 。

尽pipe您的sorting规则设置为utf8_general_ci,但我怀疑数据库,表格甚至列的字符编码可能不同。 他们是独立的设置 。 尝试:

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

用你的实际数据types代替VARCHAR(255)

得到同样的问题,用utf8mb4保存数据需要确保:

  1. character_set_client,character_set_connection,character_set_results是utf8mb4:character_set_client和character_set_connection表示客户端发送语句的字符集,character_set_results表示服务器向客户端返回查询结果的字符集。参见charset-connection

  2. 表和列编码是utf8mb4

对于JDBC,有两个解决scheme:

解决scheme一(需要重启MySQL):

1.像下面这样修改my.cnf并重新启动MySQL:

[MySQL的]

默认字符集= utf8mb4

的[mysqld]

字符集服务器= utf8mb4

核对服务器= utf8mb4_unicode_ci

这可以确保数据库和character_set_client,character_set_connection,character_set_results默认是utf8mb4。

2.将表格和列编码更改为utf8mb4

3.在jdbc连接器中指定characterEncoding = UTF-8和characterSetResults = UTF-8,导致这将覆盖character_set_client,character_set_connection,character_set_results to utf8

解决scheme二(不需要重启MySQL):

1.将表格和列编码更改为utf8mb4

2.在jdbc连接器中指定characterEncoding = UTF-8,导致jdbc连接器不支持utf8mb4。

3.像这样写你的sql语句(需要添加allowMultiQueries = true到jdbc连接器):

'SET NAMES utf8mb4; INSERT INTO Mytable …';

这将确保每个连接到服务器,character_set_client,character_set_connection,character_set_results是utf8mb4.Also看到字符集连接

就我而言,我尝试了以上的一切,没有任何工作。 我很确定,我的数据库如下所示。

 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; 

事实certificate,这个字符集是拉丁文的。 这就是为什么我不能在数据库中插入中文。

  ALTER TABLE company CONVERT TO CHARACTER SET utf8; 

这可能会帮助你。 🙂

我想结合几个post来做一个完整的答案,因为它似乎只是几个步骤。

  1. 以上build议由@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 

再次从build议之上的所有jdbc连接characterEncoding=UTF-8characterSetResults=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%') 

在编辑器中复制粘贴输出全部replace| 当连接到正确的数据库时没有任何回发到MySQL。

这就是所有必须做的,似乎都为我工作。 不是 – Dfile.encoding=UTF-8未启用,它似乎按预期工作

E2A仍有问题? 我当然是在生产,所以事实certificate,你需要检查上面做了什么,因为它有时不起作用,这里是理由和修复在这种情况下:

 show create table user `password` varchar(255) CHARACTER SET latin1 NOT NULL, `username` varchar(255) CHARACTER SET latin1 NOT NULL, 

你可以看到一些仍在拉丁试图手动更新logging:

 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) 

总之,我不得不减less这个领域的大小,以使更新工作。

现在当我运行:

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

这一切工作

它主要是由于一些unicode字符造成的。 在我的情况下,这是卢比货币符号。

要快速解决这个问题,我不得不发现导致这个错误的字符。 我复制粘贴整个文本在一个文本编辑器,如六,并用一个文本replace麻烦的人物。

做就是了

 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 ; 

我在rails项目中遇到了同样的问题:

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

解决scheme1:保存到数据库之前,通过Base64.encode64(subject)将string转换为base64,从数据库中获取后使用Base64.decode64(subject)

解决scheme2:

步骤1:更改主题栏的字符集(和sorting规则)

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

第2步:在database.yml中使用

 encoding :utf8mb4 

我的解决scheme是将列types从varchar(255)更改为blob

我只是想只适用于一个领域的变化,你可以尝试序列化字段

 class MyModel < ActiveRecord::Base serialize :content attr_accessible :content, :title end