mysql 存储汉字遇到的问题。
有的汉字不能存储
环境
- python3.7
- mysql 8.0.17
- macos
- 编码:utf8
有的汉字是生僻字,所以,存储的时候会出现
pymysql.err.InternalError: (1366, “Incorrect string value:
原因
UTF-8编码有可能是两个、三个、四个字节。Emoji表情、生僻字是4个字节,而Mysql的utf8编码最多3个字节,所以数据插不进去。
需要改变数据库的编码方式,选择 utf8mb4。
utf8 和 utf8mb4 区别
MySQL 在 5.5.3 之后增加了 utf8mb4 字符编码,mb4即 most bytes 4。简单说 utf8mb4 是 utf8 的超集并完全兼容utf8,能够用四个字节存储更多的字符。
也就是当你的数据库里要求能够存入这些表情或宽字符时,可以把字段定义为 utf8mb4,同时要注意连接字符集也要设置为utf8mb4,否则在 严格模式 下会出现 Incorrect string value: /xF0/xA1/x8B/xBE/xE5/xA2… for column 'name' 这样的错误,非严格模式下此后的数据会被截断。
utf8mb4unicodeci 与 utf8mb4generalci 如何选择
字符除了需要存储,还需要排序或比较大小,涉及到与编码字符集对应的 排序字符集(collation)。ut8mb4对应的排序字符集常用的有
utf8mb4_unicode_ciutf8mb4_general_ci
主要从排序准确性和性能两方面看:
- 准确性
utf8mb4_unicode_ci 是基于标准的 Unicode来排序和比较,能够在各种语言之间精确排序。
utf8mb4_general_ci 没有实现Unicode排序规则,在遇到某些特殊语言或字符是,排序结果可能不是所期望的。
但是在绝大多数情况下,这种特殊字符的顺序一定要那么精确吗。比如Unicode把ß、Œ当成ss和OE来看;而general会把它们当成s、e,再如ÀÁÅåāă各自都与 A 相等。
- 性能
utf8mb4_general_ci 在比较和排序的时候更快。
utf8mb4_unicode_ci 在特殊情况下,Unicode排序规则为了能够处理特殊字符的情况,实现了略微复杂的排序算法。
但是在绝大多数情况下,不会发生此类复杂比较。general理论上比Unicode可能快些,但相比现在的CPU来说,它远远不足以成为考虑性能的因素,索引涉及、SQL设计才是。
原作者推荐的是 utf8mb4_unicode_ci。
进入 mysql 环境,输入
show variables like 'character%';我最开始出现,看 character_set_database
+--------------------------+-----------------------------------------------------------+
| Variable_name | Value |
+--------------------------+-----------------------------------------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| character_sets_dir | /usr/local/mysql-8.0.17-macos10.14-x86_64/share/charsets/ |
+--------------------------+-----------------------------------------------------------+更改数据库的编码。
set character_set_database=utf8mb4;然后执行
show variables like 'character%';出现
+--------------------------+-----------------------------------------------------------+
| Variable_name | Value |
+--------------------------+-----------------------------------------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| character_sets_dir | /usr/local/mysql-8.0.17-macos10.14-x86_64/share/charsets/ |
+--------------------------+-----------------------------------------------------------+然后可以看我创建的表规则
1 | drop table IF EXISTS `t_introductions`; |
还有 python 代码。
1 | import pymysql |
最后成功存储。