MySQL only_full_group_by導致的group by錯誤解決
問題
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後的值'
-