最近把服務器上的MySQL5.6.x升級到MySQL5.7.x,使用navicat查詢SQL時,雖然可以查詢到正確的結果集,可是在正確結果集下方出現以下一段異常信息:html
[Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column 'information_schema.PROFILING.SEQ' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by mysql
這是爲何呢?能夠確定SQL語句沒有問題,在MySQL5.6.x上執行相同的SQL語句沒有任何異常,難道升級後MySQL5.7.x有細節更新?sql
Linux版本的MySQL5.x中sql_mode默認爲空,例如日期字段能夠插入'0000-00-00 00:00:00'這樣的值,還有若是要插入的字段長度超過列定義的長度,那麼MySQL不會終止操做,而是會自動截斷後面的字符繼續插入操做,以下例:
mysql> create table t5 (c1 char(3));
mysql> insert into t5 values('abcd');
mysql> select * from t5;
+------+
| c1 |
+------+
| abc |
+------+
1 row in set (0.00 sec)
咱們發現插入的字符被自動截斷了,可是若是咱們本意但願若是長度超過限制就報錯,那麼咱們能夠設置sql_mode爲STRICT_TRANS_TABLES,以下:
mysql> set session sql_mode='STRICT_TRANS_TABLES'
這樣咱們再執行一樣的操做,mysql就會告訴咱們插入的值太長,操做被終止,以下:
mysql> insert into t5 values('abcd');
ERROR 1406 (22001): Data too long for column 'c1' at row 1
經過上面的例子,對sql_mode的簡單設置,便能解決這個問題,即能控制sql規範,也可以識別"這個字符。數據庫
Windows版本的MySQL5.x的配置文件中是默認取消ONLY_FULL_GROUP_BY檢查。
參數以下:
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"服務器
對於強迫症人來講眼裏是不容沙子的,這是咱們決不容許的狀況,那麼咱們怎麼清除這段異常信息呢?session
分析ide
根據異常信息分析發現,這問題主要是因爲sql_mode引發,因此先查看sql_mode,再除ONLY_FULL_GROUP_BY參數。函數
解決方案 1this
SELECT @@sql_mode; 或 SELECT @@global.sql_mode; //全局配置
-- 修改SQL_MODE
SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
-- 或者只清除ONLY_FULL_GROUP_BY
SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY','STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'));
或
SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';注意:這種方法修改是會話級別的,重啓MySQL服務後,再執行SQL語句仍然會出現異常信息。
code
解決方案 2
修改MySQL配置文件
Windows:my.ini
Linux:my.cnf
sql_mode =ONLY_FULL_GROUP_BY,
STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION修改成
:
sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
sql_mode的做用是什麼呢?
模式定義MySQL會支持哪些SQL語法。以及應執行哪一種數據驗證檢查。
最終達到的目標:MySQL服務器可以工做在不一樣的SQL模式下,並能針對不一樣的客戶端以不一樣的方式應用這些模式。這樣,應用程序就能對服務器操做進行量身定製以知足本身的需求。這類模式定義了MySQL應支持的SQL語法,以及應該在數據上執行何種確認檢查。從而可以在衆多不一樣的環境下,與其餘數據庫服務器一塊兒更容易地使用MySQL。從MySQL 4.1 開始,也能在啓動以後,使用SET[SESSION|GLOBAL]sql_mode='mode1,mode2…'語句,經過設置sql_mode變量更改模式。
那麼ONLY_FULL_GROUP_BY是起什麼做用的?
對於GROUP BY聚合操做,若是在SELECT中的列,沒有在GROUP BY中出現,那麼這個SQL是不合法的,由於列不在GROUP BY從句中,因此對於設置了這個mode的數據庫,在使用group by 的時候,就要用MAX(),SUM(),ANT_VALUE()這種聚合函數,才能完成GROUP BY 的聚合操做。
sql_mode經常使用值
sql_mode值 | 描述 |
---|---|
TANS | 寬鬆模式,對插入數據進行校驗,若是不符合定義類型或長度,對數據類型調整或截斷保存,報warning警告 |
STRICT_TRANS_TABLES | 嚴格模式,若是不能將給定的值插入到事務表中,則放棄該語句。對於非事務表,若是值出如今單行語句或多行語句的第1行,則放棄該語句 |
TRADITIONAL | 嚴格模式,Make MySQL的行爲象「傳統」SQL數據庫系統。該模式的簡單描述是當在列中插入不正確的值時「給出錯誤而不是警告」。註釋:一旦發現錯誤當即放棄INSERT/UPDATE。若是你使用非事務存儲引擎,這種方式不是你想要的,由於出現錯誤前進行的數據更改不會「滾動」,結果是更新「只進行了一部分」。 |
說明:若是把sql_mode的值設置成後面的兩個值(也就是咱們說的嚴格模式),那麼當在列中插入或更新不正確的值時,mysql將會給出錯誤,而且放棄insert/update操做。在咱們的通常應用中建議使用這兩種模式,而不是使用默認的空或ANSI模式。可是須要注意的問題是,若是數據庫運行在嚴格模式下,而且你的存儲引擎不支持事務,那麼有數據不一致的風險存在,好比一組sql中有兩個dml語句,若是後面的一個出現了問題,可是前面的已經操做成功,那麼mysql並不能回滾前面的操做。所以說設置sql_mode須要應用人員權衡各類得失,從而獲得一個合適的選擇
sql_mode其餘值:
ONLY_FULL_GROUP_BY
對於GROUP BY聚合操做,若是在SELECT中的列,沒有在GROUP BY中出現,那麼這個SQL是不合法的,由於列不在GROUP BY從句中。
NO_AUTO_VALUE_ON_ZERO
該值影響自增加列的插入。默認設置下,插入0或NULL表明生成下一個自增加值。若是用戶但願插入的值爲0,該列又是自增加的,那麼這個選項就有用了。
STRICT_TRANS_TABLES
在該模式下,若是一個值不能插入到一個事物表中,則中斷當前的操做,對非事物表不作限制
NO_ZERO_IN_DATE
在嚴格模式下,不容許日期和月份爲零
NO_ZERO_DATE
設置該值,mysql數據庫不容許插入零日期,插入零日期會拋出錯誤而不是警告。
ERROR_FOR_DIVISION_BY_ZERO
在INSERT或UPDATE過程當中,若是數據被零除,則產生錯誤而非警告。如 果未給出該模式,那麼數據被零除時MySQL返回NULL
NO_AUTO_CREATE_USER
禁止GRANT建立密碼爲空的用戶
NO_ENGINE_SUBSTITUTION
若是須要的存儲引擎被禁用或未編譯,那麼拋出錯誤。不設置此值時,用默認的存儲引擎替代,並拋出一個異常
PIPES_AS_CONCAT
將"||"視爲字符串的鏈接操做符而非或運算符,這和Oracle數據庫是同樣的,也和字符串的拼接函數Concat相相似
ANSI_QUOTES
啓用ANSI_QUOTES後,不能用雙引號來引用字符串,由於它被解釋爲識別符
官方文檔:https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html