MySQL5.7中的sql_mode默认值
简介
在正常项目开发过程中,如果MySQL版本从5.6升级到5.7版本。作为DBA在考虑数据库版本升级带来的影响时,一般会有几个注意点:
sql_mode
默认值的改变optimizer_switch
值的改变- 备库升级影响主备复制
本文主要内容是MySQL升级到5.7版本之后,由于默认的sql_mode
值带来的坑以及对应的解决方案。
案例一:ONLY_FULL_GROUP_BY
问题描述
MySQL版本从5.6升级至5.7之后,部分SQL执行报错,报错信息如下:
1
ERROR 1055 (42000): Expression #3 of XXXXXX list is not in GROUP BY clause and contains nonaggregated column ‘XXXXX.XXXXXX’ which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
这个问题原因在于从5.6升级至5.7版本后 sql_mode
默认值发生了改变,在5.7版本的 sql_mode
默认值中有意向 ONLY_FULL_GROUP_BY
,该选项的含义表示:对于使用 GROUP BY
进行查询的SQL,不允许 SELECT
部分出现 GROUP BY
中未出现的字段,也就是 SELECT
查询的字段必须是 GROUP BY
中出现的或者使用聚合函数的或者是具有唯一属性的。
解决方案
- 方案一(不推荐):修改5.7版本
sql_mode
值,将ONLY_FULL_GROUP_BY
去掉ONLY_FULL_GROUP_BY
是加强SQL规范的,其目的是让SQL查询出来的结果更符合规范,更准确。
如果没有ONLY_FULL_GROUP_BY
规范限制,那么则能允许以下SQL的执行:SELECT a,b,c FROM t GROUP BY a
。SQL按照a字段值进行分组,当同一个a字段值对应多个b或者c值时,查询结果中的b,c值是不确定的。 - 方案二:对于不符合
ONLY_FULL_GROUP_BY
限制的字段,添加unique索引 - 方案三:改写SQL,按照规范编写SQL
- 方案四:使用ANY_VALUE(),对于不符合
ONLY_FULL_GROUP_BY
的字段使用ANY_VALUE()函数,让MySQL跳过ONLY_FULL_GROUP_BY
检测
1
2
3
4
5
6mysql> SELECT name, address, MAX(age) FROM t GROUP BY name;
ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP
BY clause and contains nonaggregated column 'mydb.t.address' which
is not functionally dependent on columns in GROUP BY clause; this
is incompatible with sql_mode=only_full_group_by
mysql>SELECT name, ANY_VALUE(address), MAX(age) FROM t GROUP BY name;
案例二:NO_ZERO_DATE & NO_ZERO_IN_DATE & time_zone
问题描述
排错阶段一
MySQL版本从5.6升级至5.7之后,创建表的过程中失败:
1 |
mysql> CREATE TABLE `t_manager` ( |
错误提示 MODIFY_DATETIME
字段设置的默认值是无效的,考虑到刚从5.6版本升级到5.7版本,于是又去翻了翻5.7中默认的 sql_mode
值。结果发现了两个可能存在影响的选项:
NO_ZERO_DATE
:MySQL中插入的时间字段值,不允许日期为零NO_ZERO_IN_DATE
:MySQL中插入的时间字段值,不允许日期和月份为零
排错阶段二
于是解决方案就是按照
NO_ZERO_DATE
以及NO_ZERO_IN_DATE
的要求设置默认值,将MODIFY_DATETIME
字段默认值设置为’1001-01-01 01:01:01’,结果发现还是无法成功创建表:1
2
3
4
5
6
7
8
9
10mysql>CREATE TABLE `t_manager` (
.....
-> `CREATE_DATETIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
-> `MODIFIER` varchar(32) DEFAULT NULL COMMENT '更新人',
-> `MODIFY_DATETIME` timestamp NOT NULL DEFAULT '1001-01-01 01:01:01' ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
-> `IS_DELETED` bit(1) DEFAULT b'0' COMMENT '删除状态 1:删除 0:未删除',
-> `IS_ENABLE` bit(1) DEFAULT b'1' COMMENT '启用状态 1:启用 0:禁用',
-> PRIMARY KEY (`CACHE_ID`)
-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ERROR 1067 (42000): Invalid default value for 'MODIFY_DATETIME'
查看了所有的 sql_mode
值,都符合规范,但是表还是创建不成功。只好去官方手册上找找timestamp介绍:
The TIMESTAMP data type is used for values that contain both date and time parts. TIMESTAMP has a range of ‘1970-01-01 00:00:01’ UTC to ‘2038-01-19 03:14:07’ UTC.
排错阶段三
可以看到官方定义中timestamp字段值的范围是’1970-01-01 00:00:01’到’2038-01-19 03:14:07’,原来是我们设置的默认值不在timestamp范围之内。于是再次修改默认值:
1 |
mysql>CREATE TABLE `t_manager` ( |
邪了门,居然还是无法成功创建表。实在是没辙了,向同事求救,同事说他在机器上试试,结果同样的语句在他的MySQL上执行成功,同样是5.7.23版本。
百思不得其解。
一气之下将两边的参数值拿出来对比了一下,果然找到了不同的根本。
测试环境 | 同事环境 |
---|---|
system_time_zone=CST | system_time_zone UTC |
time_zone=’+08:00’ | time_zone=SYSTEM |
回过头来看timestamp字段定义的范围:
The TIMESTAMP data type is used for values that contain both date and time parts. TIMESTAMP has a range of ‘1970-01-01 00:00:01’ UTC to ‘2038-01-19 03:14:07’ UTC.
这个时间范围指的是UTC时区的时间范围,测试环境设置了CST东八区的时区,则对应的时间范围上也需要对应的加8小时。所以将timestamp字段默认值修改为’1970-01-01 08:00:01’,表终于创建成功。
1 |
mysql>CREATE TABLE `mn_cache_refresh_manager` ( |
解决方案
- 将timestamp字段默认值修改为对应CST时区的最小值’1970-01-01 08:00:01’
总结
最后总结一下MySQL中5.7中sql_mode参数默认值的几个意思
- ONLY_FULL_GROUP_BY
对于使用GROUP BY
进行查询的SQL,不允许SELECT
部分出现GROUP BY
中未出现的字段,也就是SELECT
查询的字段必须是GROUP BY
中出现的或者使用聚合函数的或者是具有唯一属性的。 - STRICT_TRANS_TABLES
该选项针对事务性存储引擎生效,对于非事务性存储引擎无效,该选项表示开启strict sql模式。在strict sql模式下,在INSERT或者UPDATE语句中,插入或者更新了某个不符合规定的字段值,则会直接报错中断操作 - NO_ZERO_IN_DATE
MySQL中插入的时间字段值,不允许日期和月份为零 - NO_ZERO_DATE
MySQL中插入的时间字段值,不允许日期为零 - ERROR_FOR_DIVISION_BY_ZERO
INSERT或者UPDATE语句中,如果数据被0除,则出现警告(非strict sql模式下)或者错误(strict sql模式下)。- 当该选项关闭时,数字被0除,得到NULL且不会产生警告
- 当该选项开启且处于非strict sql模式下,数字被0除,得到NULL但是会产生警告
- 当该选项开启且处于strict sql模式下,数字被0除,产生错误且中断操作
- NO_AUTO_CREATE_USER
之前版本中使用GRANT语法,如果用户不存在则会自动创建用户,该选项限制该功能 - NO_ENGINE_SUBSTITUTION
在使用CREATE TABLE或者ALTER TABLE语法执行存储引擎的时候,如果设定的存储引擎被禁用或者未编译,会产生错误。
MySQL5.7中的sql_mode默认值的更多相关文章
- struts2视频学习笔记 03-06(Struts 2配置文件无提示问题,Action配置中的各项默认值,各种转发类型)
课时3 解决Struts 2配置文件无提示问题(eclipse):window→preference→XML→XML Catlog
- sqlserver中GUID的默认值设置
sqlserver中GUID的默认值设置 YID uniqueidentifier not null default (NEWSEQUENTIALID()), //有序GUID(只能用于表设计的时候的 ...
- c++ 中bool 的默认值
比如在Test.h中定义变量: _isFirst; //Test.h头文件 #ifndef __TEST_H__ #define __TEST_H__ class Test{ private: boo ...
- 弹窗中修改select默认值遇到的问题
弹窗中修改select默认值无效 前提: 项目中遇到一个需求, 在一个弹窗中,有很多个select都是在打开弹窗的同时由js自动生成的(每次打开都自动重新生成一遍). 弹窗打开后,从每个select的 ...
- @RequestMapping中method的默认值是什么?
@RequestMapping中method的默认值是什么? 没有默认值,如果不配置method, 则以任何请求形式 RequestMethod.GET, RequestMethod.POST, Re ...
- PostgreSQL中实现更新默认值(二)
今天我们用表继承+触发器的方案,来实现表中的更新默认值.这也许是PostgreSQL里最佳的解决方案. 一. 创建一张表,作为父表 create table basic_update( t_updat ...
- MySQL5.0+提示字段没有默认值(doesn’t have a default value)的解决方法
方法一: 打开my.ini,查找 sql-mode=”STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION” 修改为 sql ...
- js中function参数默认值
--在dreamweaver做网站时,函数定义是在一个*.js文件中,其中定义了一个func,有四个参数,function func(string1,url,flag,icon),然后在另一个asp中 ...
- es6中参数【默认值,扩展运算符】
参数默认值 1.普通参数 function info(age,name="grace"){ console.log(name); } info(); //输入:grace 2.对象 ...
随机推荐
- 课程四(Convolutional Neural Networks),第二 周(Deep convolutional models: case studies) ——3.Programming assignments : Residual Networks
Residual Networks Welcome to the second assignment of this week! You will learn how to build very de ...
- spring cloud+.net core搭建微服务架构:配置中心(四)
前言 我们项目中有很多需要配置的地方,最常见的就是各种服务URL地址,这些地址针对不同的运行环境还不一样,不管和打包还是部署都麻烦,需要非常的小心.一般配置都是存储到配置文件里面,不管多小的配置变动, ...
- IMEI
IMEI(International Mobile Equipment Identity)是国际移动设备身份码的缩写,国际移动装备辨识码,是由15位数字组成的"电子串号",它与每台 ...
- Java工程师学习指南 完结篇
Java工程师学习指南 完结篇 先声明一点,文章里面不会详细到每一步怎么操作,只会提供大致的思路和方向,给大家以启发,如果真的要一步一步指导操作的话,那至少需要一本书的厚度啦. 因为笔者还只是一名在校 ...
- 从零开始学 Web 之 Ajax(六)jQuery中的Ajax
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...
- Maven_1 安装配置
所需工具 : JDK 1.8 Maven 3.3.9 Windows 7 下载Maven 3.3.9 http://maven.apache.org/download.cgi 首先要先安装JDK. ...
- RockChip RK3326 系统编译问题总结
1. 序言 本文主要记录了RK3326平台系统编译过程中遇到的各种问题,并加以解决! 环境: 宿主Linux:Ubuntu 16.04 目标机:RK3326 (64bit) Toolchain:gcc ...
- SQL 同一张表中相同字段的内容合并为一条记录(不同字段的那一列每个记录后面加逗号)
一.创建表 create table stuUnion ( sid int identity primary key, cid int, id ) ) 二.添加数据 insert into stuUn ...
- DotNetCore学习-3.管道中间件
中间件是用于组成应用程序管道来处理请求和响应的组件.管道内的每个组件都可以选择是否将请求交给下一个组件,并在管道中调用下一个组件之前和之后执行一些操作. 请求委托被用来建立请求管道,并处理每一个HTT ...
- Navicat安装及简单使用
一.安装 下载完之后,直接解压出来就能用,看一下解压之后的目录: 双击打开下面这个文件(可以把它添加一个桌面快捷方式,或者添加到任务栏): 然后会提示你输入注册码: 回到navicat的解压出来的文件 ...