Mysql5.7版本sql錯誤:this is incompatible with sql_mode=only_full_group_by


錯誤信息

最近將測試環境做了遷移,發現在執行某一條未作任何改動的sql時,出現如下錯誤:

### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Expression #7 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'hmp-uat.trm.startTime' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
; bad SQL grammar []; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Expression #7 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'hmp-uat.trm.startTime' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

這個錯誤的意思:選擇的列沒有包含在GROUP BY子句中,而且包含了非聚合列,它在功能上不依賴於GROUP BY子句的列;這與sql mode=only_full_group_by完全不兼容。

簡單來說,就是查出來的字段必須是需要group by的這些字段中的一部分(隱約記得ORACLE是必須符合這個規則的)。

 

原因分析

上邊的是MyBatis拋出的異常信息,單獨執行SQL錯誤就是紅色的部分。未作遷移之前執行的好好的SQL,遷移后就不能正常執行了,做的事情就是換了MySQL版本,估計應該是MySQL版本導致的。原環境上mysql版本為5.6.x,新環境上的mysql我安裝的是5.7.21。

 

版本查詢

工具使用的navicat,查詢MySQL版本:

在鏈接上右鍵,打開命令行,或者直接快捷鍵F6,輸入如下命令:

select version();

結果如下:

mysql> select version(); +-------------------------+ | version() | +-------------------------+ | 5.7.21-0ubuntu0.16.04.1 | +-------------------------+ 1 row in set mysql> 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

sql_mode查詢

同樣,在命令行輸入如下命令:

select @@GLOBAL.sql_mode;

結果如下:

mysql> select @@GLOBAL.sql_mode; +-------------------------------------------------------------------------------------------------------------------------------------------+ | @@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 | +-------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set mysql> 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

可以看到,當前數據庫sql_mode確實包括了ONLY_FULL_GROUP_BY。開啟了這個模式,那么group by和select的字段就會嚴格匹配。

sql測試

接下來在5.7數據庫中做一個簡單的測試:

select id, name from t_hotel group by name
  • 1.

如上,按照name分組,但是我需要查出來id和name兩個字段,結果是拋出異常:

[SQL]select id, name from t_hotel group by name

[Err] 1055 - Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'hmp-uat.t_hotel.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

正確的SQL寫法應該是這樣:

select id, name from t_hotel group by id, name
  • 1.

需要查詢出來的列表id和name也必須作為分組的字段。

那么,這樣在寫SQL時限制較多,而且原來的應用需要改動,修改業務邏輯不太現實。最后的辦法是,將該選項關閉。

解決辦法

重新設置sql_mode,來關閉這個選項。

臨時修改

在navicate命令窗口,鍵入如下命令來修改:

set @@GLOBAL.sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
  • 1.

其實就是去掉了ONLY_FULL_GROUP_BY,在查詢sql_mode可以看到設置成功。

但是這個方法如果重啟了mysql,設置就會失效,最后的辦法是永久關閉。

永久修改

打開/etc/mysql/my.cnf配置文件,在mysqld節點下添加如下配置:

sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
  • 1.

然后重啟mysql:

service mysql restart

再次執行sql,可以看到可以成功執行,問題解決。

表名大小區分

另外,mysql5.7默認也是開啟了表明的大小寫區分的,也可以通過修改配置文件來關閉,具體如下:

打開/etc/mysql/my.cnf配置文件,在mysqld節點下添加如下配置:

lower_case_table_names=1

1代表不區分大小寫,0代表區分,改完后,重啟mysql。

總結

mysql5.7默認開啟了很多功能,如果是數據庫升級,需要關閉一些選項,例如lower_case_table_names和ONLY_FULL_GROUP_BY,肯定還有其他問題,在測試過程中慢慢發現吧。

 

轉自:https://blog.belonk.com/c/Mysql_error_only_full_group_by.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM