一、环境及问题描述 
1. 环境 
操作系统:win10,64bit。  
python版本:2.7.15  
mysql版本:5.7.23  
2. 问题描述 
使用python从某个数据文件读取数据,处理后,用MySQLdb去连接数据库表并插入数据,此时报错:  
 
 OperationalError: (1366, "Incorrect string value..."  
  
网上可以查到是编码问题:  
 
 出现这个异常是mysql问题,而非python的问题,这是因为mysql的字段类型是utf-xxx, 而在mysql中这些utf-8数据类型只能存储最多三个字节的字符,而存不了包含四个字节的字符。  
  
因为之前的数据库的字符集是utf8,所以需要转为utf8mb4编码。  
不幸的是,我装的mysql版本很老,是5.4的版本,而utf8mb4编码在5.5.3后才支持,于是只能重装mysql,重新装的是5.7.23的版本。  
   
二、关于utf8mb4编码 
MySQL在5.5.3版本之后增加了这个utf8mb4的编码,mb4就是most bytes 4的意思,专门用来兼容四字节的unicode。其实,utf8mb4是utf8的超集,理论上原来使用utf8,然后将字符集修改为utf8mb4,也会不会对已有的utf8编码读取产生任何问题。当然,为了节省空间,一般情况下使用utf8也就够了。  
既然utf8应付日常使用完全没有问题,那为什么还要使用utf8mb4呢? 低版本的MySQL支持的utf8编码,最大字符长度为 3 字节,如果遇到 4 字节的字符就会出现错误了。  
三个字节的 UTF-8 最大能编码的 Unicode 字符是 0xFFFF,也就是 Unicode 中的基本多文平面(BMP)。也就是说,任何不在基本多文平面的 Unicode字符,都无法使用MySQL原有的 utf8 字符集存储。  
   
三、问题解决 
1. 数据库编码修改 
修改my.ini的内容:  
 
 [client] 
default-character-set = utf8mb4 
[mysql] 
default-character-set = utf8mb4 
[mysqld] 
character-set-client-handshake = FALSE 
character-set-server = utf8mb4 
collation-server = utf8mb4_unicode_ci 
init_connect='SET NAMES utf8mb4'  
  
将数据库和已经建好的表也转换成utf8mb4:  
 
 ALTER DATABASE db_name CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;  
  
更改表编码:  
 
 ALTER TABLE TABLE_NAME CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;  
  
重启mysql服务。  
如果这个时候已经解决问题,可以不用往下看了。  
否则,可以看看下面的思路能否为你提供一点想法。  
我的情况是依旧没有解决问题。  
   
2. 从读取文件的编码入手 
发现数据文件的编码是gb2312,所以读取一行内容后需要转为unicode然后再转为utf8:  
 
 line = line.decode('gbk').encode('utf-8') 
  
(奇怪的是用’gb2312’就不行)  
至此问题解决。  
所以可以看出实际上我遇到的问题只是读取的编码在写入mysql的时候不能识别而已,后面我新建一个表,默认编码为utf8,也能正常插入,这也验证了这个想法。  
   
四、参考 
1. python插入数据到mysql时报错:mysql  
2. utf8mb4与utf8的区别  
3. 更改MySQL数据库的编码为utf8mb4  
(完)  |