sql_mode-ONLY_FULL_GROUP_BY
sql_mode 用于控制 MySQL 的行为
比如说 MySQL-8.0.x
sql_mode 的默认值如下。
select @@sql_mode;
+-----------------------------------------------------------------------------------------------------------------------+
| @@sql_mode |
+-----------------------------------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+-----------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
ONLY_FULL_GROUP_BY
要说清楚这个,还是要说一个以前 MySQL 校验不严格的锅,假设有如下数据。
select * from t_person;
+----+-------+-----+
| id | name | age |
+----+-------+-----+
| 1 | tom | 17 |
| 2 | jerry | 17 |
| 3 | bob | 18 |
+----+-------+-----+
3 rows in set (0.00 sec)
MySQL 以前检验不严格,我们是能写出一些逻辑上有问题,但是可以正常执行的 SQL 的。
-- 在 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_ENGINE_SUBSTITUTION";
-- 没有按 name 分组但是 name 能出现在分组过滤的条件语句中。 dog 呀!
select name, age, count(*) as cnts from t_person group by age having name='tom' ;
+------+-----+------+
| name | age | cnts |
+------+-----+------+
| tom | 17 | 2 |
+------+-----+------+
1 row in set (0.00 sec)
如果我们加上这个 SQL_MODE 类似的 SQL 在执行过程中会报错。
select name, age, count(*) as cnts from t_person group by age having name='tom' ;
ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'tempdb.t_person.name' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
还有一个差不多的场景就是 group by 之后的 order,先来一段正常的
select age, count(*) as cnts from t_person group by age order by cnts desc;
+-----+------+
| age | cnts |
+-----+------+
| 17 | 2 |
| 18 | 1 |
+-----+------+
2 rows in set (0.00 sec)
再来一段逻辑上明显有问题的 SQL 。
select age, count(*) as cnts from t_person group by age order by name desc;
ERROR 1055 (42000): Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column 'tempdb.t_person.name' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
总结
sql_mode 加上 ONLY_FULL_GROUP_BY 还是非常有必要的,至少一些逻辑上明显有错误的 SQL 语句现在可以报错了。