报错1055不是sql写错了,而是mysql 8.0默认启用only_full_group_by模式所致;需执行select @@sql_mode确认是否含该模式,再通过set session临时调整或重构sql永久修复。

报错1055不是SQL写错了,是MySQL 8.0开始严格执行SQL标准——ONLY_FULL_GROUP_BY默认开启,必须处理非聚合字段。
怎么确认真是ONLY_FULL_GROUP_BY惹的祸?
别猜,直接查:SELECT @@sql_mode;。如果返回结果里包含ONLY_FULL_GROUP_BY(通常排在最前面),就是它。注意:云数据库如阿里云RDS可能禁止SET GLOBAL,但SELECT @@sql_mode总能执行。
- 输出是英文逗号分隔的字符串,比如
'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,...' - 如果用
SELECT @@GLOBAL.sql_mode;发现没权限,就用会话级查,足够定位 - 错误信息里
Expression #2 of SELECT list is not in GROUP BY clause中的#2,对应SELECT列表里第二个未聚合、也未出现在GROUP BY里的字段
临时绕过:只影响当前连接,适合调试和CI
开发时想快速验证或跑通流水线,执行这条命令即可,断开重连自动恢复原状:
SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
- 别手拼
sql_mode值,比如SET SESSION sql_mode = 'STRICT_TRANS_TABLES,...'——容易漏项或加空格,导致ONLY_FULL_GROUP_BY还在 - JDBC里设
connectionInitSql可能被忽略,建议在应用首次查询前显式执行 - 这条命令不重启服务、不改配置,安全边界清晰
长期修复:改SQL比关模式更可靠
禁用ONLY_FULL_GROUP_BY能让老SQL跑通,但结果不可控——id、name这类字段会随机取自分组内某行,下次查询可能变。优先按语义改SQL:
- 如果只要统计值,删掉冗余字段:
SELECT status, COUNT(*) FROM user GROUP BY status - 如果字段和GROUP BY列存在函数依赖(比如
status和status_name一对一),把它加进GROUP BY:GROUP BY status, status_name - 如果业务接受“任取一个”,用
ANY_VALUE()显式表达意图:SELECT ANY_VALUE(id), status, COUNT(*) FROM user GROUP BY status(注意:这是MySQL特有,跨库迁移需重写)
永久关模式?小心配置文件里的坑
真要全局关,得改my.cnf,但极易出错:
- 别在
sql_mode值里加单引号或多余空格,比如sql_mode='STRICT_TRANS_TABLES,...'会导致MySQL启动失败 - 必须写完整值,不能只写想保留的几项——MySQL会自动补全默认项,
ONLY_FULL_GROUP_BY可能悄悄回来 - Docker环境改
/etc/mysql/my.cnf或/etc/mysql/mysql.conf.d/mysqld.cnf,改完docker restart,别只reload
真正麻烦的从来不是那条SET SESSION命令,而是旧SQL里那些没声明意图的非聚合字段——它们在线上跑了几百次,没人知道哪次会返回哪一行的name。











