mysql的ONLY_FULL_GROUP_BY语义 --转自http://www.wtoutiao.com/p/19dh3ec.html
执行SET GLOBAL sql_mode = ''; 把sql_mode 改成非only_full_group_by模式。验证是否生效 SELECT @@GLOBAL.sql_mode 或 SELECT @@sql_mode
STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION
ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
sql_mode常用值如下: 
ONLY_FULL_GROUP_BY:
对于GROUP BY聚合操作,如果在SELECT中的列,没有在GROUP BY中出现,那么这个SQL是不合法的,因为列不在GROUP BY从句中
NO_AUTO_VALUE_ON_ZERO:
该值影响自增长列的插入。默认设置下,插入0或NULL代表生成下一个自增长值。如果用户 希望插入的值为0,而该列又是自增长的,那么这个选项就有用了。
STRICT_TRANS_TABLES:
在该模式下,如果一个值不能插入到一个事务表中,则中断当前的操作,对非事务表不做限制
NO_ZERO_IN_DATE:
在严格模式下,不允许日期和月份为零
NO_ZERO_DATE:
设置该值,mysql数据库不允许插入零日期,插入零日期会抛出错误而不是警告。
ERROR_FOR_DIVISION_BY_ZERO:
在INSERT或UPDATE过程中,如果数据被零除,则产生错误而非警告。如 果未给出该模式,那么数据被零除时MySQL返回NULL
NO_AUTO_CREATE_USER:
禁止GRANT创建密码为空的用户
NO_ENGINE_SUBSTITUTION:
如果需要的存储引擎被禁用或未编译,那么抛出错误。不设置此值时,用默认的存储引擎替代,并抛出一个异常
PIPES_AS_CONCAT:
将"||"视为字符串的连接操作符而非或运算符,这和Oracle数据库是一样的,也和字符串的拼接函数Concat相类似
ANSI_QUOTES:
启用ANSI_QUOTES后,不能用双引号来引用字符串,因为它被解释为识别符
ORACLE的sql_mode设置等同:PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS, NO_AUTO_CREATE_USER.
如果使用mysql,为了继续保留大家使用oracle的习惯,可以对mysql的sql_mode设置如下:
在my.cnf添加如下配置
[mysqld]
sql_mode='ONLY_FULL_GROUP_BY,NO_AUTO_VALUE_ON_ZERO,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,
ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,PIPES_AS_CONCAT,ANSI_QUOTES'
ONLY_FULL_GROUP_BY是mysql提供的一个sql_mode,通过这个sql_mode来提供SQL语句合法性的检查,在mysql的sql_mode=default的情况下是非ONLY_FULL_GROUP_BY语义,也就是说一条select语句,mysql允许target list中输出的表达式是除聚集函数,group by column以外的表达式,这个表达式的值可能在经过group by操作后变成undefined,无法确定(实际上mysql的表现是分组内第一行对应列的值),例如:
而对于语义限制都比较严谨的多家数据库,如SQLServer、Oracle、PostgreSql都不支持select target list中出现语义不明确的列,这样的语句在这些数据库中是会被报错的,所以mysql在后续的版本中出了一个修正语义,就是我们所说的ONLY_FULL_GROUP_BY语义,例如:
这种sql_mode下,刚才通过的查询语句被server拒绝掉了!
所以ONLY_FULL_GROUP_BY的语义就是确定select target list中的所有列的值都是明确语义,简单的说来,在ONLY_FULL_GROUP_BY模式下,target list中的值要么是来自于聚集函数的结果,要么是来自于group by list中的表达式的值。但是由于表达式的表现形式非常丰富,对于程序来说,很难精确的确定一些表达式的输出结果是明确的,比如:
在上面的查询语句中,其实c2的值也是能被唯一确定的,但是由于程序无法分析出这种复杂的关系,所以这条查询也被拒绝掉了。
我们来看下哪些语句是在mysql的ONLY_FULL_GROUP_BY模式下是被支持的。
这条query满足ONLY_FULL_GROUP_BY的限制:
target list中的max(c1+1), count(c1), min(c1)引用到的basic column都是出现在聚集函数中,c2出现在group by list中。
mysql> select c1, max(c2) from t1 group by c2;
ERROR 1055 (42000): 'yuming.t1.c1' isn't in GROUP BY
这条query被server拒绝掉了,因为target list中的c1没有出现在聚集函数中,并且也没有出现在group by list中
这条语句中c1虽然出现在了group
 by list中,但是在mysql看来,group
by中的list是c1+2这个表达式整体,mysql无法分析出c1在这个表达式中的单调性,所以这条语句也被拒绝掉了。同理还有select c1
from t1 group by
c1+1;而这样的查询分析在SQLServer中被做的更好,在SQLServer中,这样的查询,SQLServer认为是合理的。
这条语句target list中的c1+1和group by中的c1+1是严格匹配的,所以mysql认为target list中的c1+1是语义明确的,因此该语句可以通过。
因此,如果查询语句中的target
 list, having condition 或者order by list里引用了的表达式不是聚集函数,但是和group by
list中的表达式严格匹配,该语句也是合法的(c1+1和c1+1是严格匹配的,c1+1和c1+2在mysql认为是不严格匹配的,
c1+1和1+c1也是不严格匹配的)
mysql允许target
 list中对于非聚集函数的alias column被group by、having condition以及order
by语句引用(version 5.7中允许having condition引用alias column,version 5.6不支持having
 condition引用alias column),从上面两条语句可以看出,group by和order by中引用了alias
column,并且其等价于基础列语义
从上面的语句可以看出,mysql的ONLY_FULL_GROUP_BY模式支持对basic column进行组合但是不支持对于复杂表达式进行组合,这个受限于表达式分析程度。
总结一下:
mysql对于ONLY_FULL_GROUP_BY语义的判断规则是,如果group
 by list中的表达式是basic column,那么target list中允许出现表达式是group by list中basic
column或者alias column的组合结果,如果group by list中的表达式是复杂表达式(非basic
column或者alias column),那么要求target list中的表达式必须能够严格和group by
list中的表达式进行匹配,否者这条查询会被认为不合法。
由于阿里集团使用到mysql集群的业务都是默认打开了ONLY_FULL_GROUP_BY模式,所以OceanBase支持了ONLY_FULL_GROUP_BY模式,大部分的规则都是兼容mysql的行为,由于OB使用到的plan_cache策略,会对查询语句中的常量进行参数化,所以在语义检查的时候,所有常量表达式都是无法匹配的,因此在OB的ONLY_FULL_GROUP_BY模式下,含常量表达式的group
 by list是非法的,例如:select c1+1 from t1 group by
c1+1,这条语句在OB的ONLY_FULL_GROUP_BY模式下会被拒绝掉,如果用于有group by常量的需求,可以使用alias
column这个特性,例如上面的语句可以改写为:select c1+1 as a from t1 group by
a这条语句在OB的ONLY_FULL_GROUP_BY模式下是被支持的。
在下一篇文章中,我将介绍一种更精确的分析算法,可以将ONLY_FULL_GROUP_BY语义下group by list的合法性检查做得更加灵活。
mysql的ONLY_FULL_GROUP_BY语义 --转自http://www.wtoutiao.com/p/19dh3ec.html的更多相关文章
- MySQL 5.7默认ONLY_FULL_GROUP_BY语义介绍
		
mysql 5.7版本 出现 ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corre ...
 - Mysql的ONLY_FULL_GROUP_BY
		
今天在测试环境遇到一个问题,本地测试是没有问题,在测试环境sql报错了: nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntax ...
 - MySQL sql_mode=only_full_group_by错误
		
今天在测试服务器上突然出现了这么一个MySQL的问题,同样的代码正式服没有问题,那肯定就是出在了配置上,查了一下原因才明白原来是数据库版本为5.7以上的版本, 默认是开启了 only_full_gro ...
 - 基于【 bug解决】一 || mysql的ONLY_FULL_GROUP_BY导致的sql语句错误
		
一.Mysql错误: In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated ...
 - mysql sql_mode=only_full_group_by错误解析
		
实测,解决问题; 1.错误提示: 2.检查参数设置: 3.mysql的配置文件my.cnf里面可以修改, 但是,改完以后,你检查所有的参数设置都是对的,就是运行不了.怎么办?怎么办? 4.如果还是不行 ...
 - mysql sql_mode=only_full_group_by问题?
		
视图查询的时候本地数据库报错: 解决办法: 1.查看sql_mode select @@global.sql_mode STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_Z ...
 - mysql sql_mode=only_full_group_by问题临时解决
		
执行代码 set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZER ...
 - MySql 5.7 新特性概览
		
安全的提升 1.1 在Mysql 8版本中,caching_sha2_password 是一个缺省的认证插见.5.7 版本的客户端支持 caching_sha2_password 的客户端认证. 1. ...
 - 从Oracle迁移到MySQL的各种坑及自救方案
		
当企业内部使用的数据库种类繁杂时,或者有需求更换数据库种类时,都可能会做很多数据迁移的工作.有些迁移很简单,有些迁移可能就会很复杂,大家有没有考虑过为了顺利完成复杂的数据库迁移任务,都需要考虑并解决哪 ...
 
随机推荐
- JQuery设置和去除disabled属性
			
//两种方法设置disabled属性 $('#areaSelect').attr("disabled",true); $('#areaSelect').attr("dis ...
 - python核心编程第六章练习6-12
			
6-12.字符串.(a)创建一个名字为findchr()的函数,函数声明如下.def findchr(string, char)findchr()要在字符串string中查找字符char,找到就返回该 ...
 - android应用保活机制
			
android应用保活的基本原理: 都是通过双进程互拉以及设置进程的重要性,除非你root后 把自己的进程设置成系统进程. 互拉的方式有很多种 1.可以通过监听系统广播来把自己拉起来 2.可以多个ap ...
 - Sphinx 的介绍和原理探索——不存储原始数据,原始数据来源于SQL,而生成索引放在内存或者磁盘中
			
摘自:http://blog.jobbole.com/101672/ What/Sphinx是什么 定义:Sphinx是一个全文检索引擎. 特性: 索引和性能优异 易于集成SQL和XML数据源,并可使 ...
 - SSH集成log4j日志环境[转]
			
第一步:在web.xml初始化log4j <context-param> <param-name>log4jConfigLocation</param-name> ...
 - C#驱动及应用
			
一,使用开源客户端:StackExchange.Redis 二,使用方法: 1,获取访问redis数据库连接,代码如下. /// <summary> /// 获取访问redis数据 ...
 - 谈谈Javascript的this关键字(this is not this)
			
前言: 看文章标题你就知道,这篇文章我只讲一个简单的Javascript的this关键字,说它简单——它又不简单,因为曾几何时我也对this关键字有些困惑,它也确实会让不少程序员感到不解——它像是一个 ...
 - 什么是Angular? 我们为什么要学习它?
			
在我更新Ionic的时候有人问我什么是 Angular,我们为什么要学习它啊?这个是我的疏忽了,在没有告诉你们什么是 Angular 的时候就让大家着手去学习 Ionic .那么今天就让我们认识一下什 ...
 - 对已经发布订阅的sqlserver进行修改-添加新的表
			
1.以服务器名称连接数据库 2.找到复制-本地发布-对应的数据库发布订阅-右键属性-选择项目-选择新增的表(没有看到,注意取消右侧的仅显示列表已选择的项目) 3.然后重新初始化所有订阅 4.如果出现“ ...
 - scp不可用:WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED
			
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! After doing ssh are you seeing this error.No proble ...