mysql中的sql_mode设置


sql_mode是个很容易被忽视的变量,默认值是空值,在这种设置下是可以允许一些非法操作的,比如允许一些非法数据的插入。


一些现象

之前开发的时候,发现一些奇怪的情况:

我一个字段设置为NOT NULL,而且不给其设置默认值,就算执行的插入sql中没有这个字段,mysql也会给字段填充上对应类型的默认值(int=>0,varchar=>空字符串)。

还有就是比如一个字段是varchar(20),然后我插入一个长度为200的字符串也同样不会报错,数据库会自动截取字符串来入库。

类似的情况还有,不过我发现mysql都不会报错,还会自动帮助转换。


新问题

今天朋友说,他一个字段设置为NOT NULL,且没给默认值,插入的时候报错了。1364:xx字段没有默认值。

奇怪的是,同样代码,且mysql数据库版本一致的本地缺没有报错,只有线上报错了。

百度找到答案后,我发现,之前我遇到这个问题,一直还以为是mysql的版本问题,今天才知道,不是的。。。

是因为线上和本地的mysql变量sql_mode的设置不同,他线上设置了很多值,校验相当的严格了。(严格模式),而我之前所有的设置都是直接为空,或者就是简单的 NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION (宽松模式)


sql_mode常用值

可以使用sql语句 show variables like 'sql_mode'; 来查看你当前 sql_mode 的设置。

修改设置的话,在mysql配置文件(my.ini 或 my.cnf)中的 [mysqld] 模块下。

以下列举了几个常用值,和简单解释:

1. ONLY_FULL_GROUP_BY

对于GROUP BY聚合操作,如果在SELECT中的列,没有在GROUP BY中出现,那么这个SQL是不合法的,因为列不在GROUP BY从句中

如果不想改数据库配置,可以试着在select取的字段加函数绕过验证,比如 MAX(name), ABS,SUM之类的


2. NO_AUTO_VALUE_ON_ZERO

该值影响自增长列的插入。默认设置下,插入0或NULL代表生成下一个自增长值。如果用户 希望插入的值为0,而该列又是自增长的,那么这个选项就有用了。


3. STRICT_TRANS_TABLES

在该模式下,如果一个值不能插入到一个事务表中,则中断当前的操作,对非事务表不做限制


4. NO_ZERO_IN_DATE

在严格模式下,不允许日期和月份为零


5. ERROR_FOR_DIVISION_BY_ZERO

在INSERT或UPDATE过程中,如果数据被零除,则产生错误而非警告。如 果未给出该模式,那么数据被零除时MySQL返回NULL


6. NO_AUTO_CREATE_USER:

禁止GRANT创建密码为空的用户


7. NO_ENGINE_SUBSTITUTION

如果需要的存储引擎被禁用或未编译,那么抛出错误。不设置此值时,用默认的存储引擎替代,并抛出一个异常


8. ANSI_QUOTES

启用ANSI_QUOTES后,不能用双引号来引用字符串,因为它被解释为识别符


最后

具体怎么设置看个人,我自己是比较喜欢宽松模式的,具体字段值的校验放在代码层来做,在入库前做检查。

我的设置:

[mysqld]
sql_mode="NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"


mysql


上一篇:HTTP缓存机制详解(转)

多个微信小程序应用的微信支付:下一篇