問題
MySQL5.7以上版本,默認是開啟了 only_full_group_by模式的:
> select @@sql_mode
> select @@global.sql_mode;
ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
開啟這個模式后,原先的 group by 語句就報錯:
SELECT list is not in GROUP BY clause and contains nonaggregated column 'test' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
原因
MySQL在低版本(5.7.x 以下)中允許 select 后面的非聚合列不出現在 group by 中。以下sql在低版本中是可以運行的,但是在5.7及以上版本會報錯:
select name, age, count(name) from student group by age
因為在SQL標准中,出現在select target list中,並且沒有出現在聚集函數中的表達式必須出現在group by子句中:
-
order by后面的列必須是在
select中存在 -
select、having或order by后面存在的非聚合列必須全部在group by中存在
而沒有遵循原則的sql會被認為是不合法的sql,如SQLServer、Oracle、PostgreSql都不支持select target list中出現語義不明確的列,MySQL 5.7開始修正,即ONLY_FULL_GROUP_BY語義。
解決
開啟 only_full_group_by ,group by 將變成和 distinct 一樣,只能獲取受到其影響的字段信息,無法和其他未受其影響的字段共存,這樣,group by 的功能將變得十分狹窄。
-
保持
only_full_group_by模式開啟MySQL提供了any_value(field)函數允許非分組字段的出現(和關閉 only_full_group_by 模式有相同效果)。select any_value(name), age, count(name) from student group by age -
關閉only_full_group_by
-
當前會話關閉:
只在當前會話生效,關閉當前會話就失效。
> select @@sql_mode復制查詢出來的值,去除
only_full_group_by,再設置回去:> set sql_mod='去除only_full_group_by后的值'比如:在
navicat中當前窗口執行,在當前窗口生效,新開窗口失效。 -
當前服務關閉:
當前服務生效,重啟服務失效(該方法,我設置好像不生效?)
> select @@global.sql_mode復制查詢出來的值,去除
only_full_group_by,再設置回去:> set global sql_mod='去除only_full_group_by后的值' -
修改MySQL程序配置:
需重啟
MySQL生效。永久生效,但生產環境上是禁止重啟MySQL服務。MySQL配置文件my.conf目錄:# mysql --help | grep 'my.cnf' order of preference, my.cnf, $MYSQL_TCP_PORT, /etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnf從左到右優先級,后者覆蓋前者重復參數。
添加:
[mysqld] sql_mode=去除only_full_group_by后的值 -
JDBC參數關閉only_full_group_by:jdbc:mysql://localhost:3306/test?sessionVariables=sql_mode='去除only_full_group_by后的值'
-
