MySQL的sql_mode配置

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

参考:mysql5.6设置sql_mode方法详解

更优的解决方案

  • 如果发现出错的字符是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 忽略字符错误

参考:MySQL解决插入emoji表情失败的问题
参考:Python 在什么情况下会输出 Unicode 字符串

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操作类似,授权之前必须先建立用户。
  • 数据检查
    • STRICT_ALL_TABLES 表示启用严格模式,指 INSERT、UPDATE出现少值或无效值该如何处理:
      1. 前面提到的把 ‘’ 传给int,严格模式下非法,若启用非严格模式则变成0,产生一个warning
      2. Out Of Range,变成插入最大边界值
      3. 当新插入的行不包含某列的没有显示定义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

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

你可能感兴趣的:(mysql)