MySQL5.7版本sql_mode=only_full_group_by问题解决办法

本文解析了MySQL5.7版本中因ONLY_FULL_GROUP_BY设置导致的Group By错误,介绍了错误产生的原理及解决方案。

在服务器数据库查询使用了 GROUP BY 居然报出了

1055 - Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'csc_risk.a.DefaultDate' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by, Time: 0.035000s 

一、原理层面
这个错误发生在mysql 5.7 版本及以上版本会出现的问题:
mysql 5.7版本默认的sql配置是:sql_mode="ONLY_FULL_GROUP_BY",这个配置严格执行了"SQL92标准"。
很多从5.6升级到5.7时,为了语法兼容,大部分都会选择调整sql_mode,使其保持跟5.6一致,为了尽量兼容程序。
二、sql层面
在sql执行时,出现该原因:
简单来说就是:输出的结果是叫target list,就是select后面跟着的字段,还有一个地方group by column,就是
group by后面跟着的字段。由于开启了ONLY_FULL_GROUP_BY的设置
如果一个字段没有在target list和group by字段中同时出现,或者是聚合函数的值的话,那么这条sql查询是被mysql认为非法的,会报错误。

于是把部分数据迁移到本地进行测试, 发现sql语句可以执行并查看数据库版本

原因分析:MySQL5.7版本默认设置了 mysql sql_mode = only_full_group_by 属性,导致报错。

为了验证是不是数据版本问题, 于是查询版本

SELECT VERSION()

查询数据版本发现确实是5.7版本

知道原因就好办, 查询怎么解决.  

下载安装的是最新版的mysql5.7.x版本,默认是开启了 only_full_group_by 模式的,但开启这个模式后,原先的 group by 语句就报错,然后又把它移除了。

一旦开启 only_full_group_by ,感觉,group by 将变成和 distinct 一样,只能获取受到其影响的字段信息,无法和其他未受其影响的字段共存,这样,group by 的功能将变得十分狭窄了

only_full_group_by 模式开启比较好。因为在 mysql 中有一个函数: any_value(field) 允许,非分组字段的出现(和关闭 only_full_group_by 模式有相同效果)。

1、查看sql_mode
 

SELECT @@sql_mode;

查询出来的值为:

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

2、去掉ONLY_FULL_GROUP_BY,重新设置值。

SET @@global.sql_mode ='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';


3、上面是改变了全局sql_mode,对于新建的数据库有效。对于已存在的数据库,则需要在对应的数据下执行

windows 在安装目录下的my.ini 文件
Mac 或者Linux 在/ etc/my.cnf 下面应该是

总之就是在mysql配置文件中修改

在[mysqld]下面添加这段

sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION  
MySQL 中 `sql_mode=ONLY_FULL_GROUP_BY` 的问题通常出现在 5.7 及以上版本中,这是因为默认的 SQL 模式启用了 `ONLY_FULL_GROUP_BY`,它要求 `SELECT` 子句中的所有字段都必须出现在 `GROUP BY` 子句中,否则会抛出错误。以下是几种解决方案: ### 1. 修改 SQL 模式(全局设置) 可以通过修改 MySQL 的全局 SQL 模式来移除 `ONLY_FULL_GROUP_BY`。这可以通过以下 SQL 语句实现: ```sql SET GLOBAL sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'; ``` 该方法会立即生效,但仅在 MySQL 服务运行期间有效。重启 MySQL 后,设置会失效。如果需要永久生效,则需要修改 MySQL 的配置文件 `my.ini` 或 `my.cnf` 文件[^3]。 在配置文件的 `[mysqld]` 部分添加以下内容: ```ini sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION ``` 保存文件后重启 MySQL 服务[^1]。 ### 2. 临时修改当前会话的 SQL 模式 如果你只想在当前会话中修改 SQL 模式,可以使用以下语句: ```sql SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'; ``` 这种方式只对当前连接有效,断开连接后设置会失效[^3]。 ### 3. 使用 `ANY_VALUE()` 函数 如果无法修改 SQL 模式,可以在 `SELECT` 语句中使用 `ANY_VALUE()` 函数来绕过 `ONLY_FULL_GROUP_BY` 的限制。例如: ```sql SELECT ANY_VALUE(name), ANY_VALUE(sex), salary FROM employees GROUP BY salary; ``` `ANY_VALUE()` 函数告诉 MySQL 优化器,即使某些字段没有出现在 `GROUP BY` 子句中,也可以安全地选择它们。MySQL 会从每组中随机选择一个值返回[^3]。 ### 4. 修改查询语句以符合 `ONLY_FULL_GROUP_BY` 规则 如果希望保留 `ONLY_FULL_GROUP_BY` 模式,可以修改查询语句,确保 `SELECT` 子句中的所有字段都包含在 `GROUP BY` 子句中,或者使用聚合函数如 `MAX()`、`MIN()`、`SUM()` 等来处理非分组字段。例如: ```sql SELECT name, sex, salary FROM employees GROUP BY name, sex, salary; ``` 或者使用聚合函数: ```sql SELECT MAX(name), MAX(sex), salary FROM employees GROUP BY salary; ``` 这种方法虽然更符合 SQL 标准,但可能会增加查询复杂度[^2]。 ### 5. 针对特定数据库或表的设置 如果需要对特定数据库或表进行设置,可以在对应的数据库中执行以下语句: ```sql SET sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'; ``` 这将影响当前数据库的所有查询,但不会影响其他数据库[^4]。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fish_study_csdn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值