前言  

  在一次使用group by查询数据库时,遇到了问题。下面先搭建环境,然后让问题复现,最后分析问题。

一 问题复现

  mysql版本

  

  建表插入数据

  

  表的结构

  

  现在问题来了:我想查询上面表中每个部门年龄最大的人。

  sql语句:select NAME,dept,MAX(age) from mytable group by dept;

  

  此时会发现:查询结果中,dept 和 max(age) 是正确的,但是name却是错误的!!!因为34岁的101部门应该指向 li4 ,36岁的102部门应该是 tian7。

二 分析原因

  对于上面的问题主要要注意两个方面:

  1.为什么很多网上的帖子会出现这个sql语句查询报错的情况?

  2.为什么这种sql语句能执行但是查询结果不正确?

  

  下面针对这两个方面进行展开说明:

  1.

    有很多人可能使用上面的sql语句查询会报错,抛出这样的错误

    

    翻译过来就是:select list的表达式1不在group by子句中,并且包含非聚合列“test.mytable.name”,该列在功能上不依赖于group by子句中的列;这与sql _mode=only_full _group _by不兼容

    既然这里提到了sql_mode,那我就来查查sql_mode,如果你抛出了上面的错误,那么你的sql_mode中一定包含 ONLY_FULL_GROUP_BY

    show variables like 'sql_mode';

    

    什么是sql_mode?

    官方解释:

      The MySQL server can operate in different SQL modes, and can apply these modes differently for different clients, depending on the value of the sql_mode system variable. DBAs can set the     global SQL mode to match site server operating requirements, and each application can set its session SQL mode to its own requirements

    中文翻译:

      mysql服务器可以在不同的SQL模式下运行,并且可以根据sql_模式系统变量的值,为不同的客户机应用这些模式。DBA可以设置全局SQL模式以匹配站点服务器操作需求,并且每个应用程序        都可以将其会话SQL模式设置为自己的需求。

    同时:

      sql_mode是个很容易被忽视的变量,默认值是空值,在这种设置下是可以允许一些非法操作的,比如允许一些非法数据的插入。在生产环境必须将这个值设置为严格模式,所以开发、测试环境       的数据库也必须要设置,这样在开发测试阶段就可以发现问题。

    在我们使用group by进行查询语句时,如果查询字段不在聚合列中(也就是group by后面的列),实际上这种sql语句是错误的,也是没有意义的,mysql是可以不支持这种查询方式的。在我们生产环      境中,最好将sql_mode设置为严格模式,这样在开发阶段就能发现问题,排除错误、无效的sql语句。

    ONLY_FULL_GROUP_BY就是规定了你不能使用错误、无效的group by去查询数据,所以,如果你的sql_mode是ONLY_FULL_GROUP_BY,那么执行上面那条sql语句就会抛出错误了。

  2.

    那为什么我使用上面的sql语句查询时,没有抛出错误,自然也就得到了解释,因为我当时的sql_mode 是这样的:

    

    并不包含ONLY_FULL_GROUP_BY,同时,我们看到的查询结果是错误的,这也从反面说明了 mysql规定的一些sql_mode的必要性,就是因为某些sql语句会出现问题,但是又不能及时被发现。所以     在开发环境中,使用合适的严格的sql_mode 至关重要。

三 有哪些sql_mode?

  官方说明先放在这: https://dev.mysql.com/doc/refman/5.6/en/sql-mode.html

  简单介绍如下:

  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后,不能用双引号来引用字符串,因为它被解释为识别符

四 如何设置sql_mode

  sql_mode的设置分为局部(session)设置和全局(global)设置 下面是我从mysql官网直接拿过来的:

  session就是指 你设置的sql_mode只会在你当前会话有效,当你注销用户,重新登录mysql后,仍然是你默认的sql_mode

  global就是指全局的。

  设置GLOBAL变量需要该SUPER权限,并影响从该时间开始连接的所有客户端的操作。设置SESSION变量仅影响当前客户端。每个客户端都可以随时更改其会话sql_mode值

  

  另外的一种设置方式:

  直接修改mysql配置文件,打开mysql配置文件可以看到:

  

  这个sql_mode也就是我默认的,也可以在此处修改。

  最后多说一点,虽然mysql规定了这么多sql_mode用来约束sql语句规范,但是并不是每一个sql_mode都要配上,我们要在合适的环境选择合适的配置

另,原创,转载注明出处!

      

由group by引发的sql_mode的学习的更多相关文章

  1. 由SecureCRT引发的思考和学习

    由SecureCRT引发的思考和学习 http://mp.weixin.qq.com/s?__biz=MzAxOTAzMDEwMA==&mid=2652500597&idx=1& ...

  2. 由简单的CMD命令引发的一场学习战斗

    想要打开一个软件时,由于桌面没有存放快捷方式,又忘了软件存放在电脑上的哪个角落.脑海里突然闪过一个想法:用CMD自定义软件的打开方式,于是问了度娘.由此,引发了一场停不下来的CMD学习战斗. 爱上CM ...

  3. js 一道题目引发的正则的学习

    正则表达式中的特殊字符 字符 含意 \ 做为转意,即通常在"\"后面的字符不按原来意义解释,如/b/匹配字符"b",当b前面加了反斜杆后/\b/,转意为匹配一个 ...

  4. [转]如何正确学习JavaScript

    原文:How to Learn JavaScript Properly(2014-2-7) 学习时长:6-8周 学习前提:中学水平,无需编程经验 更新(2014-1-7) 在Reddit上创建了一个学 ...

  5. 不用写代码就能实现深度学习?手把手教你用英伟达 DIGITS 解决图像分类问题

    2006年,机器学习界泰斗Hinton,在Science上发表了一篇使用深度神经网络进行维数约简的论文 ,自此,神经网络再次走进人们的视野,进而引发了一场深度学习革命.深度学习之所以如此受关注,是因为 ...

  6. 理解一条语句:SELECT difference(sum("value")) FROM "mq_enqueue" WHERE "channel" =~ /ActiveMQ_TEST/ AND $timeFilter GROUP BY time($interval)

    最近使用grafana在查询InfluxDB中,用到了这一条语句 SELECT difference(sum("value")) FROM "mq_enqueue&quo ...

  7. 【目录】Spring 源码学习

    [目录]Spring 源码学习 jwfy 关注 2018.01.31 19:57* 字数 896 阅读 152评论 0喜欢 9 用来记录自己学习spring源码的一些心得和体会以及相关功能的实现原理, ...

  8. linux初级学习笔记六:linux用户及权限详解!(视频序号:03_4)

    本节学习的命令:/etc/passwd,/etc/shadow,/etc/group文件详解 本节学习的技能: 安全上下文 文件与目录的权限管理 影子命令 用户,用户组类别详解 /etc/passwd ...

  9. KNN学习笔记

    简单地说,KNN算法就是通过测量不同特征值之间的距离来对特征进行分类的一种算法. 优点:精度高.对异常值不敏感.无数据输入假定. 缺点:计算复杂度高.空间复杂度高. 适用数据范围:数值型和标称型. 工 ...

随机推荐

  1. 微信小程序开发--页面结构

    一.微信小程序开发--页面文件组成 [page.name].js 页面逻辑文件,用于创建页面对象,以及处理页面生命周期控制和数据处理 [page.name].wxml wxml指的是Wei Xin M ...

  2. MyBatis:choose标签的用法

    <!-- 4.2 choose用法 需求: 在已有的sys_user表中,除了主键id外,我们认为user_name也是唯一的, 所有的用户名都不可以重复.现在进行如下查询:当参数id有值的时候 ...

  3. 多个数据库 migration

    More than one DbContext was found. Specify which one to use. Use the '-Context' parameter for PowerS ...

  4. Mysql常用增删查改及入门(二)

    常用:数据库常用就是DML:增删查改 1.增加数据: insert into 表名 values (值1,值2...); insert into 表名 (字段1,字段2) values (值1,值2) ...

  5. React躬行记(3)——组件

    组件(Component)由若干个React元素组成,包含属性.状态和生命周期等部分,满足独立.可复用.高内聚和低耦合等设计原则,每个React应用程序都是由一个个的组件搭建而成,即组成React应用 ...

  6. .NET Core CSharp初级篇 1-8泛型、逆变与协变

    .NET Core CSharp初级篇 1-8 本节内容为泛型 为什么需要泛型 泛型是一个非常有趣的东西,他的出现对于减少代码复用率有了很大的帮助.比如说遇到两个模块的功能非常相似,只是一个是处理in ...

  7. 跟着阿里p7一起学java高并发 - 第18天:玩转java线程池,这一篇就够了

    java中的线程池,这一篇就够了 java高并发系列第18篇文章. 本文主要内容 什么是线程池 线程池实现原理 线程池中常见的各种队列 自定义线程创建的工厂 常见的饱和策略 自定义饱和策略 线程池中两 ...

  8. SpringBoot日志相关

    SpringBoot使用的是SLF4j当门面,Logback当实现完成 日志级别 数字越大,级别越高,框架只会输出大于等于当前日志级别的信息 ERROR 40 WARN 30 INFO 20 DEBU ...

  9. HDU 多校 第三场 Find the answer

    这题是原来cf上的一道原题,不过对于有一些数据范围修改了,不过还是很好想的 题意:给定一个长度为N的数组,对于数组中的每个位置,满足当前和小于M所需要去掉的最小代价 分析:对于当前是否需要进行去掉一些 ...

  10. web安全脑图