本文已参与「新人创作礼」活动,一起开启掘金创作之路。
问题发现的场景
- 最近在协助网友部署项目的时候,运行项目出现以下Mysql报错:
Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column ‘表名.列名’ which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
问题的描述
字面意思理解:
- SELECT 列表的表达式 #1 不在 GROUP BY 子句中,并且包含非聚合列“grades.order_id”
- 它在功能上不依赖于GROUP BY 子句中的列; 这与 sql_mode=only_full_group_by 不兼容
- 其实是使用GROUP BY 语句违背了sql_mode=only_full_group_by。因为mysql版本5.7之后默认的模式是ONLY_FULL_GROUP_BY。
原理分析
- 在 MySQL 5.7.5 之前,启用 ONLY_FULL_GROUP_BY 会禁用此扩展,因此需要使用非别名表达式编写 HAVING 子句。
- 从 MySQL 5.7.5 开始,此限制被取消,因此 HAVING 子句可以引用别名,无论是否启用了 ONLY_FULL_GROUP_BY。
- MySQL 5.7.5和以后的版本实现了对功能依赖的检测。
- 如果启用了only_full_group_by SQL模式(在默认情况下是这样)
- 那么MySQL就会拒绝选择列表、条件或顺序列表引用的查询
- 这些查询将引用组中未命名的非聚合列,而不是在功能上依赖于它们。
- 在5.7.5之前,MySQL没有检测到功能依赖项,only_full_group_by在默认情况下是不启用的。
- 查看官方文档,发现从 MySQL 5.7.5 开始,默认 SQL 模式包括 ONLY_FULL_GROUP_BY。
- 在 5.7.5 之前,MySQL 不检测函数依赖,并且默认不启用 ONLY_FULL_GROUP_BY。这可能会导致一些sql语句失效。
问题解决
- 执行以下sql命令,可以查看 sql_mode 的内容。
- 最后能发现原来是mysql 8.0 以上取消了NO_AUTO_CREATE_USER这个关键字,在mysql中的sql_mode中删掉这个关键字即可。
SELECT @@sql_mode;
SET GLOBAL sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
FLUSH PRIVILEGES;
- 实测可行,修改成功!