项目场景:
将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 列表中所有未使用聚合函数(如 COUNT、SUM、AVG)的列,都出现在 GROUP BY 子句中。
步骤说明:
- 分析报错信息,找到是
SELECT列表中的第几列(例如 Expression #11)未在GROUP BY中。 - 将该列名添加到
GROUP BY子句末尾。 - 如果该列在业务逻辑上确实需要分组,此修改是安全的;如果不需要,请考虑使用聚合函数或方案三。
示例代码(修改前):
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 行为的场景。
步骤说明:
-
查看当前 sql_mode: 运行
SELECT @@sql_mode;确认是否包含ONLY_FULL_GROUP_BY。 -
移除 ONLY_FULL_GROUP_BY(会话级): 仅影响当前数据库连接。
sqlSET SESSION sql_mode = (SELECT REPLACE(@@sql_mode, 'ONLY_FULL_GROUP_BY', '')); -
移除 ONLY_FULL_GROUP_BY(全局级,需权限): 影响所有后续连接。
sqlSET GLOBAL sql_mode = (SELECT REPLACE(@@GLOBAL.sql_mode, 'ONLY_FULL_GROUP_BY', '')); -
永久修改(配置文件): 修改 MySQL 配置文件(如
my.cnf或my.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 中出现的非聚合列,任意选择一个值即可。这是兼顾标准兼容性和灵活性的推荐做法。
步骤说明:
- 确定
SELECT列表中哪些非聚合列未出现在GROUP BY中。 - 使用
ANY_VALUE(column_name)函数包裹这些列。 - 执行修改后的 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): 如果业务逻辑允许,确保
SELECT和GROUP BY列一致是最规范的。 - 次选方案三(ANY_VALUE): 当无法修改
GROUP BY列(例如性能考虑或复杂查询)时,使用ANY_VALUE()是官方推荐的兼容方式。 - 临时方案二(修改 sql_mode): 仅作为快速测试或临时绕过使用,生产环境慎用,因为它可能掩盖潜在的数据不一致问题。