MySQL 5.7.5+ 或 8.0 默认启用 ONLY_FULL_GROUP_BY 导致 1055 错误,需通过 SELECT @@sql_mode 确认;可临时 SET SESSION 修改、永久修改配置文件,或改 SQL(补 GROUP BY、用 ANY_VALUE() 等)。

新装的 MySQL(5.7.5+ 或 8.0)默认启用 ONLY_FULL_GROUP_BY,这不是你 SQL 写错了,是它在按 SQL 标准校验语义合法性 —— 只要 SELECT 列里有非聚合字段、又没出现在 GROUP BY 中,就直接报错 1055。
怎么确认真是 ONLY_FULL_GROUP_BY 在作怪
别猜,先查:SELECT @@sql_mode; 或 SELECT @@GLOBAL.sql_mode;。如果返回值里包含 ONLY_FULL_GROUP_BY(通常还跟着 STRICT_TRANS_TABLES 等),那 1055 就是它引起的。
- 注意区分
@@sql_mode(当前会话)和@@GLOBAL.sql_mode(全局); - 有些驱动(比如 ADO.NET)会在执行
INSERT ... RETURNING前悄悄改 session 的sql_mode,但不恢复,导致后续GROUP BY报错 —— 这种情况查的是 session 模式,不是全局; - 云 RDS 实例可能禁止修改
GLOBAL,但允许改 session,得看权限。
临时绕过:只对当前连接生效
适合本地调试、CI 流水线单次运行,或你暂时没权限改配置:
- 执行
SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode, 'ONLY_FULL_GROUP_BY', ''));; - 更稳妥的做法是显式列出剩余项:
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';; - 切勿用
SET GLOBAL sql_mode = ''清空全部模式,会关掉所有严格检查,比如插入超长字符串会被静默截断,数据可能出问题。
永久关闭:改配置文件并重启
线上环境该走这条路,但必须注意位置和写法:
- Linux 找
/etc/my.cnf,Windows 找C:\ProgramData\MySQL\MySQL Server X.X\my.ini; - 只在
[mysqld]段下添加或修改sql_mode行,**删掉ONLY_FULL_GROUP_BY,其余项保留**; - 不能写成
sql-mode(带横线),也不能放在[client]段下; - 保存后必须重启服务:
sudo systemctl restart mysqld(Linux)或net stop mysql && net start mysql(Windows); - 重启后务必再执行
SELECT @@GLOBAL.sql_mode;确认ONLY_FULL_GROUP_BY已消失。
不改数据库,只改 SQL:最安全但要动代码
如果你用的是云 RDS 且无变量修改权限,或者团队强制要求兼容标准 SQL,那就得调整查询本身:
- 把所有非聚合列补进
GROUP BY,例如SELECT user_id, user_name, COUNT(*) FROM orders GROUP BY user_id, user_name; - 用
ANY_VALUE()包裹非确定性字段(MySQL 5.7.5+ 支持),如SELECT user_id, ANY_VALUE(user_name), COUNT(*) FROM orders GROUP BY user_id; - 用
MAX()/MIN()等聚合函数替代,前提是业务能接受“取最大/最小值”这个语义; - 注意:
ORDER BY里引用的非聚合列,同样受ONLY_FULL_GROUP_BY约束,也得处理。
最容易被忽略的是驱动程序偷偷改 sql_mode 后不恢复 —— 它不会报错,但会让后续同连接的 GROUP BY 突然失败,排查时容易误判为 SQL 本身问题。


















