关于MySQL - SELECT list is not in GROUP BY clause and contains nonaggregated column错误

Posted by Geuni's Blog on April 16, 2022

错误信息:

1
[42000][1055] Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'mydb.t.address' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

MySQL 5.7.5及以上版本开始,默认开启了ONLY_FULL_GROUP_BY选项。

当分组查询中的SELECT,ORDER BY中出现非GROUP BY中的列,这违背了SQL-92标准,该模式下就会报错。(不过也有一些例外,可参考官方文档

下面是MySQL 5.7默认的sql_mode,可以看到第一个模式就是ONLY_FULL_GROUP_BY。

mysql_sql_mode

如果只是当前在写的SQL报这个错误,最好是重新审查一下SQL代码并重写。 如果想从数据库层面想放宽标准来解决该问题,那只需把sql_mode中的ONLY_FULL_GROUP_BY模式取消就行。(如果是已经上线的系统需谨慎开启该模式,如果是项目初期可以开启该模式来约束开发人员编写更为标准的SQL)

打开你的mysql配置文件

1
2
3
4
5
6
7
8
9
10
vi /usr/local/etc/my.cnf

#如果不知道自己的配置文件在哪,可尝试如下步骤。
➜  ~ which mysqld
/usr/local/opt/mysql@5.7/bin/mysqld

➜  ~ /usr/local/opt/mysql@5.7/bin/mysqld --verbose --help | grep -A 1 "Default options"
Default options are read from the following files in the given order:
/etc/my.cnf /etc/mysql/my.cnf /usr/local/etc/my.cnf ~/.my.cnf

添加如下配置项

1
2
[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

重启服务生效。

如果想runtime中修改该模式(无需重启),可以登陆MySQL执行如下命令:

1
2
3
4
## 全局生效
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';
# 当前会话级别生效
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';

修改后执行如下命令,确认当前的sql_mode:

1
2
SELECT @@GLOBAL.sql_mode;
SELECT @@SESSION.sql_mode;