MySQL: 与only_full_group_by模式不兼容的两个解决办法

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: MySQL: 与only_full_group_by模式不兼容的两个解决办法

20210727173609413.jpg

1. 异常现象

数据库在迁移后执行SQL出现了问题, 报错信息如下

SELECT list is not in GROUP BY clause and contains nonaggregated column 
'cloud.exam_train_user.user_id' which is not functionally 
dependent on columns in GROUP BY clause; 
this is incompatible with sql_mode=only_full_group_by

image.gif

可以看出是因为sql_mode中设置了only_full_group_by模式引起的

在这个模式下,我们使用分组查询时,出现在select字段后面的只能是group by后面的分组字段,或使用聚合函数包裹着的字段。

Oracled等数据库都不支持select target list中出现语义不明确的列,这样的语句在这些数据库中是会被报错的,所以从MySQL 5.7版本开始修正了这个语义,就是所说的ONLY_FULL_GROUP_BY语义。

MySQL 官方解释

20210727170453510.png

image.gif

MySQL 5.7.5 及更高版本默认开启了ONLY_FULL_GROUP_BY的 SQL 模式

解决方法

方法1: 修改sql_mode

可以通过select @@sql_mode查出sql_mode以后去掉ONLY_FULL_GROUP_BY后复制过来

查询sql_mode设置,发现有ONLY_FULL_GROUP_BY

mysql> select version(),@@sql_mode;
+------------+----------------------------------------------------------------+
| version()  | @@sql_mode                                                     |
+------------+----------------------------------------------------------------+
| 5.7.29-log | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+------------+----------------------------------------------------------------+
1 row in set (0.00 sec)

image.gif

修改sql_mode设置

临时修改

set sql_mode=' ' //改变已经存在的数据库sql_mode

set @@global.sql_mode=' ' //改变全局配置sql_mode

以上配置在重启服务以后失效

更改配置文件(推荐使用)

    • linux系统更改/etc/my.cnf文件
    • windows下配置文件是安装目录下的my.ini文件

    如果有sql_mode=...的注释就把注释打开,如果没有就加上sql_mode=...

    sql_mode = 'STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

    image.gif

    MySQL5.7: my.cnf参数速查小册子

    方法2: select非group by的字段

    直接修改修改sql_mode设置, 很多时候对于开发人员时没有权限的, DBA也需要很慎重地修改,因此对于开发人员, 我们可以在SQL层面进行优化

    通过上文,我们知道,

    如果sql_mode中设置了only_full_group_by模式

    在这个模式下,我们使用分组查询时,出现在select字段后面的只能是group by后面的分组字段,或使用聚合函数包裹着的字段。

    因此,此时在含有Group by子句的查询语句中,对select关键字后的目标列,存在以下规律

      1. 使用group by 时,select 涉及的列要么是参与分组的列,要么列包含在聚合函数中
      2. where将对分组前的所有数据进行筛选。having将对分组后的一组数据搞事情。

      例如:

      select a,b,avg(c),sum(d) from 表 group by a,b

      image.gif

      select非group by的字段

        • 可以把group by的结果集当作一个表,然后从这里表里取数就可以了
        • 例如:查询,订单表中订单号重复的订单信息,分组字段是orderno,select的信息不仅有orderno,还有其他信息
        SELECT
          p.id,
          p.orgcode,
          p.idserial,
          p.username,
          p.orderno,
          p.createtime,
          p.payflag,
          p.businessorderno,
          p.paytime
        FROM
          pay_order_trade p,
          (
            SELECT
              orderno,
              count(*) 重复次数
            FROM
              pay_order_trade
            GROUP BY
              orderno
            HAVING
              count(1) > 1
          ) s
        WHERE
          s.orderno = p.orderno
        ORDER BY
          p.orderno DESC;

        image.gif

        MySQL 5.7: sql_mode

        模式会影响 MySQL 支持的 SQL 语法以及它执行的数据验证检查。

        这使得在不同环境中使用 MySQL 以及与其他数据库服务器一起使用 MySQL 变得更容易。

        设置 SQL 模式

        在MySQL 5.7的默认SQL模式包括以下模式:ONLY_FULL_GROUP_BYSTRICT_TRANS_TABLESNO_ZERO_IN_DATENO_ZERO_DATEERROR_FOR_DIVISION_BY_ZERONO_AUTO_CREATE_USER,和 NO_ENGINE_SUBSTITUTION

        这些模式已添加到 MySQL 5.7 中的默认 SQL 模式: ONLY_FULL_GROUP_BYSTRICT_TRANS_TABLES模式已添加到 MySQL 5.7.5 中。该 NO_AUTO_CREATE_USER模式是在 MySQL 5.7.7 中添加的。的 ERROR_FOR_DIVISION_BY_ZERONO_ZERO_DATE以及 NO_ZERO_IN_DATE在MySQL 5.7.8添加模式。有关对默认 SQL 模式值的这些更改的其他讨论,请参阅 MySQL 5.7 中的 SQL 模式更改

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

        更多信息参考: https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html

        参考连接

        https://dev.mysql.com/doc/refman/5.7/en/dynindex-sqlmode.html

        https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

        https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html

        相关实践学习
        如何在云端创建MySQL数据库
        开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
        全面了解阿里云能为你做什么
        阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
        目录
        相关文章
        |
        2月前
        |
        数据采集 中间件 关系型数据库
        Mac系统通过brew安装mysql5.7后,启动报错的解决办法
        Mac系统通过brew安装mysql5.7后,启动报错的解决办法
        |
        5月前
        |
        Prometheus 监控 关系型数据库
        数据库同步革命:MySQL GTID模式下主从配置的全面解析
        数据库同步革命:MySQL GTID模式下主从配置的全面解析
        641 0
        |
        1月前
        |
        SQL 关系型数据库 MySQL
        MySQL异常一之: You can‘t specify target table for update in FROM clause解决办法
        这篇文章介绍了如何解决MySQL中“不能在FROM子句中指定更新的目标表”(You can't specify target table for update in FROM clause)的错误,提供了错误描述、需求说明、错误做法和正确的SQL写法。
        436 0
        |
        3月前
        |
        SQL 关系型数据库 MySQL
        MySQL的match WITH QUERY EXPANSION 模式是什么?如何使用?
        【8月更文挑战第29天】MySQL的match WITH QUERY EXPANSION 模式是什么?如何使用?
        61 4
        |
        3月前
        |
        关系型数据库 MySQL
        MySQL 8.0 - Authentication plugin ‘caching_sha2_password‘ cannot be loaded 原因及解决办法
        MySQL 8.0 - Authentication plugin ‘caching_sha2_password‘ cannot be loaded 原因及解决办法
        177 1
        |
        3月前
        |
        SQL 关系型数据库 MySQL
        问题1:Navicat连接不上mysql8的简单解决办法
        问题1:Navicat连接不上mysql8的简单解决办法
        1221 2
        |
        5月前
        |
        SQL 关系型数据库 MySQL
        解决 MySQL 5.7 及以上版本中的 “ONLY_FULL_GROUP_BY“ 错误
        解决 MySQL 5.7 及以上版本中的 “ONLY_FULL_GROUP_BY“ 错误
        1002 3
        |
        4月前
        |
        分布式计算 DataWorks 关系型数据库
        MaxCompute操作报错合集之配置mysql数据源querysql模式,同步到MC时遇到报错,该怎么处理
        MaxCompute是阿里云提供的大规模离线数据处理服务,用于大数据分析、挖掘和报表生成等场景。在使用MaxCompute进行数据处理时,可能会遇到各种操作报错。以下是一些常见的MaxCompute操作报错及其可能的原因与解决措施的合集。
        |
        5月前
        |
        JSON 关系型数据库 MySQL
        实时计算 Flink版产品使用问题之在使用CDAS语法同步MySQL数据到Hologres时,如果开启了字段类型宽容模式,MySQL中的JSON类型会被转换为什么
        实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
        |
        5月前
        |
        分布式计算 DataWorks 关系型数据库
        DataWorks操作报错合集之数据源同步时,使用脚本模式采集mysql数据到odps中,使用querySql方式采集数据,在脚本中删除了Reader中的column,但是datax还是报错OriginalConfPretreatmentUtil - 您的配置有误。如何解决
        DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。