Fix Issuse
遇到问题
在MySQL5.5中,插入到数据库的时候遇到非法字符会打印warning:
1 row(s) affected, 1 warning(s): 1366 Incorrect string value: '\xEF\xBF\xBD' for column 'Value' at row 1
但是升级到MySQL5.6版本以后,插入到数据库的时候遇到非法字符会报错:
ERROR 1366 (HY000): Incorrect string value: '\xEF\xBF\xBD' for column 'Value' at row 1
定位原因
原来从MySQL5.6版本开始,在执行mysql_install_db命令时(该命令一般在编译完mysql后运行并对数据库进行初始配置)会将默认的一个my.cnf文件写入到安装路径中(CentOS下默认安装路径为/usr/local/mysql/),其包含的信息如下:
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
更优的解决方案
- 如果发现出错的字符是emoj表情,可以采用utf8mb4编码
UTF-8编码每个字符最多占3个字节,但是我们日常用的emoji表情无法用UTF-8表示,要用到他的超集 utf8mb4 - 把非UTF-8字符转成二进制表示:python中把非UTF-8字符转码为unicode_escape
somestr.decode("utf-8", "ignore").encode("unicode_escape")
- 如果还是存在非法字符,再修改sql_mode 忽略字符错误
SQL_MODE的配置说明
常用的sql_mode
- SQL语法支持
- ONLY_FULL_GROUP_BY
对于GROUP BY聚合操作,如果在SELECT中的列、HAVING或者ORDER BY子句的列,没有在GROUP BY中出现,那么这个SQL是不合法的。是可以理解的,因为不在 group by 的列查出来展示会有矛盾。
在5.7中默认启用,所以在实施5.6升级到5.7的过程需要注意: - ANSI_QUOTES
启用 ANSI_QUOTES 后,不能用双引号来引用字符串,因为它被解释为识别符,作用与 ` 一样。
设置它以后,update t set f1=”” …,会报 Unknown column ‘’ in ‘field list 这样的语法错误。 - PIPES_AS_CONCAT
将 || 视为字符串的连接操作符而非 或 运算符,这和Oracle数据库是一样的,也和字符串的拼接函数 CONCAT() 相类似 - NO_TABLE_OPTIONS
使用 SHOW CREATE TABLE 时不会输出MySQL特有的语法部分,如 ENGINE ,这个在使用 mysqldump 跨DB种类迁移的时候需要考虑。 - NO_AUTO_CREATE_USER
字面意思不自动创建用户。在给MySQL用户授权时,我们习惯使用 GRANT … ON … TO dbuser 顺道一起创建用户。设置该选项后就与oracle操作类似,授权之前必须先建立用户。
- ONLY_FULL_GROUP_BY
- 数据检查
- STRICT_ALL_TABLES 表示启用严格模式,指 INSERT、UPDATE出现少值或无效值该如何处理:
- 前面提到的把 ‘’ 传给int,严格模式下非法,若启用非严格模式则变成0,产生一个warning
- Out Of Range,变成插入最大边界值
- 当新插入的行不包含某列的没有显示定义DEFAULT子句的值,则该值被丢弃
- STRICT_TRANS_TABLES 表示对使用innodb引擎的表启用严格模式
- NO_ZERO_DATE
认为日期 ‘0000-00-00’ 非法,与是否设置后面的严格模式有关。
如果设置了严格模式,则 NO_ZERO_DATE 自然满足。但如果是 INSERT IGNORE 或 UPDATE IGNORE,’0000-00-00’依然允许且只显示warning - NO_ENGINE_SUBSTITUTION
使用 ALTER TABLE或CREATE TABLE 指定 ENGINE 时, 需要的存储引擎被禁用或未编译,该如何处理。启用NO_ENGINE_SUBSTITUTION时,那么直接抛出错误;不设置此值时,CREATE用默认的存储引擎替代,ATLER不进行更改,并抛出一个 warning
- STRICT_ALL_TABLES 表示启用严格模式,指 INSERT、UPDATE出现少值或无效值该如何处理:
sql_mode组合
- ANSI
REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE - TRADITIONAL(5.6以后默认)
STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER, NO_ENGINE_SUBSTITUTION
参考:MySQL sql_mode 说明(及处理一起 sql_mode 引发的问题)
参考:MySQL 5.6 Reference Manual: Server SQL Modes