MySQL错误-this is incompatible with sql_mode=only_full_group_by完美解决方案

项目场景:

将jar包部署至linix运行,运行时提示 : com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException 异常报错


问题描述

MySQLSyntaxErrorException 异常报错内容如下:

复制代码
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: 
Expression #11 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'springcloud.comment_user.nikename' 
which is not functionally dependent on columns in GROUP BY clause; 
this is incompatibcle with sql_mode=only_full_group_by

原因分析:

这个异常表示在 MySQL 查询语句执行时,SELECT 列表中的一些字段未在 GROUP BY 子句中出现,可能会导致输出结果不一致或者不正确。

在设置 sql_mode 为 only_full_group_by 的情况下,MySQL 数据库会禁止此类型的查询。

在 MySQL 5.7.5 版本之后,默认SQL模式中包含了ONLY_FULL_GROUP_BY选项,要求在GROUP BY子句中的所有列都必须出现在SELECT语句中,并且不能含有聚合函数的列


解决方案:

针对 MySQL 的 ONLY_FULL_GROUP_BY 模式导致的 Expression #N of SELECT list is not in GROUP BY clause 错误,以下是三种具体、可操作的解决方案,请根据您的实际情况选择。

方案一:修改 SQL 查询语句,确保 SELECT 中的非聚合列都在 GROUP BY 中

这是最符合 SQL 标准且推荐的做法。确保 SELECT 列表中所有未使用聚合函数(如 COUNTSUMAVG)的列,都出现在 GROUP BY 子句中。

步骤说明:

  1. 分析报错信息,找到是 SELECT 列表中的第几列(例如 Expression #11)未在 GROUP BY 中。
  2. 将该列名添加到 GROUP BY 子句末尾。
  3. 如果该列在业务逻辑上确实需要分组,此修改是安全的;如果不需要,请考虑使用聚合函数或方案三。

示例代码(修改前):

sql 复制代码
-- 错误示例:SELECT 中包含非聚合列 'nikename',但 GROUP BY 中只有 'user_id'
SELECT user_id, nikename, COUNT(*) AS comment_count
FROM comment_user
GROUP BY user_id;

示例代码(修改后):

sql 复制代码
-- 正确示例:将 'nikename' 也加入 GROUP BY
SELECT user_id, nikename, COUNT(*) AS comment_count
FROM comment_user
GROUP BY user_id, nikename;

方案二:临时修改 MySQL 的 sql_mode,移除 ONLY_FULL_GROUP_BY

此方案通过修改 MySQL 会话或全局的 sql_mode 设置,临时禁用 ONLY_FULL_GROUP_BY 检查。适用于需要快速绕过错误,且能接受非标准 SQL 行为的场景。

步骤说明:

  1. 查看当前 sql_mode: 运行 SELECT @@sql_mode; 确认是否包含 ONLY_FULL_GROUP_BY

  2. 移除 ONLY_FULL_GROUP_BY(会话级): 仅影响当前数据库连接。

    sql 复制代码
    SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode, 'ONLY_FULL_GROUP_BY', ''));
  3. 移除 ONLY_FULL_GROUP_BY(全局级,需权限): 影响所有后续连接。

    sql 复制代码
    SET GLOBAL sql_mode = (SELECT REPLACE(@@GLOBAL.sql_mode, 'ONLY_FULL_GROUP_BY', ''));
  4. 永久修改(配置文件): 修改 MySQL 配置文件(如 my.cnfmy.ini),在 [mysqld] 段添加或修改:

    复制代码
    sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

    然后重启 MySQL 服务。

注意事项: 此方案降低了 SQL 的严格性,可能导致查询结果不确定性,建议仅在明确业务逻辑无误时使用。

方案三:使用 ANY_VALUE() 函数包裹非聚合列

MySQL 5.7 及以上版本提供了 ANY_VALUE() 函数,用于明确告诉数据库:对于未在 GROUP BY 中出现的非聚合列,任意选择一个值即可。这是兼顾标准兼容性和灵活性的推荐做法。

步骤说明:

  1. 确定 SELECT 列表中哪些非聚合列未出现在 GROUP BY 中。
  2. 使用 ANY_VALUE(column_name) 函数包裹这些列。
  3. 执行修改后的 SQL 语句。

示例代码(修改前):

sql 复制代码
-- 错误示例:同方案一
SELECT user_id, nikename, COUNT(*) AS comment_count
FROM comment_user
GROUP BY user_id;

示例代码(修改后):

sql 复制代码
-- 正确示例:对 'nikename' 使用 ANY_VALUE()
SELECT user_id, ANY_VALUE(nikename) AS nikename, COUNT(*) AS comment_count
FROM comment_user
GROUP BY user_id;

提示: 如果您的业务逻辑中,user_id 确定唯一对应一个 nikename,那么使用 ANY_VALUE(nikename) 是安全且高效的。这也是解决流程中推荐采用的方案。

方案选择建议

  • 优先方案一(修改 SQL): 如果业务逻辑允许,确保 SELECTGROUP BY 列一致是最规范的。
  • 次选方案三(ANY_VALUE): 当无法修改 GROUP BY 列(例如性能考虑或复杂查询)时,使用 ANY_VALUE() 是官方推荐的兼容方式。
  • 临时方案二(修改 sql_mode): 仅作为快速测试或临时绕过使用,生产环境慎用,因为它可能掩盖潜在的数据不一致问题。
相关推荐
步行cgn2 小时前
MyBatis 动态 SQL 完全指南
sql·tomcat·mybatis
️学习的小王2 小时前
MySQL常用函数知识点总结
数据库·mysql·oracle
万亿少女的梦1683 小时前
基于Spring Boot、Java与MySQL的同城宠物服务系统设计与实现
java·spring boot·mysql·系统设计·协同过滤
万亿少女的梦1683 小时前
基于Spring Boot、Vue与MySQL的私人健身教练预约管理系统设计
java·spring boot·mysql·vue·预约管理
Csvn13 小时前
📊 SQL 入门 Day 18:索引原理
后端·sql
DBA小马哥13 小时前
关系型数据库核心概念手册:SQL、事务与存储引擎的技术脉络
数据库·sql
灯澜忆梦13 小时前
【MySQL12】进阶篇 | SQL优化
数据库·sql·mysql·性能优化
2501_9159214316 小时前
抓包鹰 Traceeagle 解除证书绑定,SSL Pinning 解除
网络·网络协议·网络安全·ios·adb·https·ssl
盗理者20 小时前
AI Agent 技能分享|SQL 性能诊断与优化
java·sql·spring·skill