mysql从5.7升级到8.0后ONLY_FULL_GROUP_BY是升级后应用报错的第一大原因

mysql从5.7升级到8.0之后,GROUP BY 行为变化最常见------ONLY_FULL_GROUP_BY 是升级后应用报错的第一大原因。啥意思?

你提到的这句话,是 MySQL 从 5.7 升级到 8.0 后开发者最常遇到的兼容性问题之一。我们来一步步解释清楚:


🔍 一、核心概念:ONLY_FULL_GROUP_BY 是什么?

ONLY_FULL_GROUP_BY 是 MySQL 中 sql_mode(SQL 模式) 的一个选项,它控制着 GROUP BY 语句的严格程度。

  • ✅ 开启时(默认在 5.7+ 和 8.0) :

    要求 SELECT 列表中的每一个非聚合字段 ,都必须出现在 GROUP BY 子句中。

  • ❌ 关闭时(如 MySQL 5.6 默认) :

    允许 SELECT 中包含未在 GROUP BY 中出现的字段(即使它们不是聚合函数),MySQL 会"随便选一行"的值返回------这其实不符合 SQL 标准,结果可能不可预测。

💡 这个模式是为了让 MySQL 更符合 SQL-92 标准。


🧨 二、为什么升级后会报错?

假设你有一张表:

sql 复制代码
CREATE TABLE orders (
  id INT,
  user_id INT,
  product VARCHAR(50),
  amount DECIMAL(10,2)
);

在 MySQL 5.6(或关闭 ONLY_FULL_GROUP_BY 时),以下 SQL 是允许的:

sql 复制代码
SELECT user_id, product, SUM(amount)
FROM orders
GROUP BY user_id;

✅ 虽然 product 没有出现在 GROUP BY 中,也没有用聚合函数(如 MAX()),但 MySQL 5.6 会"容忍"它,返回每个用户分组中某一条记录的 product 值(不确定是哪条)。


但在 MySQL 5.7 / 8.0(默认开启 ONLY_FULL_GROUP_BY):

执行上面的 SQL 会直接报错:

复制代码
ERROR 1055 (42000): 
Expression #2 of SELECT list is not in GROUP BY clause 
and contains nonaggregated column 'orders.product' 
which is not functionally dependent on columns in GROUP BY clause; 
this is incompatible with sql_mode=only_full_group_by

❌ 错误意思:product 字段既不在 GROUP BY 中,又不是聚合函数(如 SUM, MAX),所以不被允许!


🛠 三、如何解决?

✅ 方法 1:改写 SQL(推荐)

让查询符合标准:

sql 复制代码
-- 方案 A:把 product 加入 GROUP BY
SELECT user_id, product, SUM(amount)
FROM orders
GROUP BY user_id, product;

-- 方案 B:对 product 使用聚合函数
SELECT user_id, MAX(product) AS product, SUM(amount)
FROM orders
GROUP BY user_id;

✅ 这是最安全、可移植、逻辑清晰的做法。


⚠️ 方法 2:关闭 ONLY_FULL_GROUP_BY(不推荐)

临时关闭(仅当前会话):

sql 复制代码
SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_DATE,...'; -- 去掉 ONLY_FULL_GROUP_BY

永久关闭(修改配置文件 my.cnf):

ini 复制代码
[mysqld]
sql_mode = STRICT_TRANS_TABLES,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

❌ 风险:可能导致查询结果不一致、隐藏逻辑错误,且违背 SQL 标准。


📌 四、为什么说这是"升级后第一大报错原因"?

因为:

  1. 很多老项目(尤其 PHP、Java 应用)在 MySQL 5.6 时代写了大量"宽松"的 GROUP BY 语句;
  2. 升级到 5.7/8.0 后,默认开启了严格模式;
  3. 应用突然大面积报错,开发者一脸懵;
  4. 必须逐条检查并修正 SQL,或临时关闭该模式。

✅ 总结

项目 说明
问题本质 MySQL 5.7+ 默认启用 ONLY_FULL_GROUP_BY,强制 GROUP BY 符合 SQL 标准
典型错误 SELECT 中有非聚合字段未出现在 GROUP BY 中
正确做法 改写 SQL:要么加入 GROUP BY,要么用聚合函数包裹
临时绕过 修改 sql_mode 关闭该选项(不推荐用于生产)

🎯 最佳实践:始终编写符合 SQL 标准的查询,避免依赖 MySQL 的"宽松模式",这样无论升级到哪个版本都不会出问题。

相关推荐
zyseo84 小时前
谷歌SEO 准首页词挖掘脚本:找出排在第 8-20 名的隐藏流量
大数据·数据库·人工智能
xiaogai_gai6 小时前
仅查询策略实战:从金蝶云·星空旗舰版定时拉取收料通知单
大数据·数据库·python
数据工匠老o6 小时前
异构数据库DDL同步:260条链路的结构变更自动适配方案
数据库·架构
L0016 小时前
MySQL5.7 DATE 字段无法设置默认日期?用触发器搞定|个人任务清单项目实战
mysql
这个DBA有点耶7 小时前
银行业市占率最高的国产数据库是谁?先搞清楚“市占率”的四种口径
数据库·程序员·架构
用户6279947182628 小时前
南大通用GBase 8a之基于审计日志的冷温热数据分析
数据库
数据库小学妹8 小时前
数据库运维五级成熟度:监控、备份、高可用怎么串起来
运维·数据库·监控
一个天蝎座的程序猿8 小时前
为了给报表提速,我把金仓KES的列存储折腾了个遍:聊聊KES的技术能力
数据库
飞越未来云城的霓虹飞猪8 小时前
AI 数据库地图:从 PostgreSQL 到向量数据库,一次看懂 AI 时代的数据底座
数据库
不像程序员的程序媛8 小时前
导出mysql数据结构
数据库·mysql