3.宽松模式 和 严格模式 的注意事项:
【1】注意:MySQL5.6和MySQL5.7默认的sql_mode模式参数是不一样的。
5.6的mode是NO_ENGINE_SUBSTITUTION,其实表示的是一个空值,相当于没有什么模式设置,可以理解为宽松模式。
5.7的mode是STRICT_TRANS_TABLES,也就是严格模式。
【2】如果设置的是宽松模式,那么我们在插入数据的时候,即便是给了一个错误的数据,也可能会被接受,并且不报错。
例如:我在创建一个表时,该表中有一个字段为name,给name设置的字段类型时char(10),如果我在插入数据的时候,其中name这个字段对应的有一条数据的长度超过了10,例如'1234567890abc',超过了设定的字段长度10,那么不会报错,并且取前十个字符存上,也就是说你这个数据被存为了'1234567890',而'abc'就没有了,但是我们知道,我们给的这条数据是错误的,因为超过了字段长度,但是并没有报错,并且mysql自行处理并接受了,这就是宽松模式的效果。
其实在开发、测试、生产等环境中,我们应该采用的是严格模式,出现这种错误,应该报错才对,所以MySQL5.7版本就将sql_mode默认值改为了严格模式,并且我们即便是用的MySQL5.6,也应该自行将其改为严格模式。
另外,MySQL等等的这些数据库,都是想把关于数据的所有操作都自己包揽下来,包括数据的校验,其实好多时候,我们应该在自己开发的项目程序级别将这些校验给做了,虽然写项目的时候麻烦了一些步骤,但是这样做之后,我们在进行数据库迁移或者在项目的迁移时,就会方便很多。mysql除了数据校验之外,你慢慢的学习过程中会发现,它能够做的事情还有很多很多,将你程序中做的好多事情都包揽了。
【3】改为严格模式后可能会存在的问题:
若设置模式中包含了NO_ZERO_DATE,那么MySQL数据库不允许插入零日期,插入零日期会抛出错误而不是警告。
例如:表中含字段TIMESTAMP列(如果未声明为NULL或显示DEFAULT子句)将自动分配DEFAULT '0000-00-00 00:00:00'(零时间戳),也或者是本测试的表day列默认允许插入零日期 '0000-00-00' COMMENT '日期';这些显然是不满足sql_mode中的NO_ZERO_DATE而报错。
4.模式设置和修改(以解决上述问题为例):
【方式一】:
先执行select @@sql_mode,复制查询出来的值并将其中的NO_ZERO_IN_DATE,NO_ZERO_DATE删除,然后执行set sql_mode = '修改后的值'或者set session sql_mode='修改后的值';
例如:set session sql_mode='STRICT_TRANS_TABLES';改为严格模式
注意:此方法只在当前会话中生效,关闭当前会话就不生效了。
【方式二】:
先执行select @@global.sql_mode,复制查询出来的值并将其中的NO_ZERO_IN_DATE,NO_ZERO_DATE删除,然后执行set global sql_mode = '修改后的值'。
注意:此方法在当前服务中生效,重新MySQL服务后失效
【方法三】:
1.在mysql的安装目录下,或my.cnf文件(windows系统是my.ini文件),新增 sql_mode =
"ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
添加my.ini如下:
[mysqld]
sql-mode="ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
2.然后重启mysql。以管理员身份运行CMD,执行 net stop mysql ,再执行 net start mysql。
注意:此方法永久生效.当然生产环境上是禁止重启MySQL服务的,所以采用‘方式二+方式三'来解决线上的问题,那么即便是有一天真的重启了MySQL服务,也会永久生效了。
总结