一、發現問題
1、查詢語句
SELECT
* from class group by class_name;
2、報錯結果
..... this
is
incompatible
with
sql_mode=only_full_group_by;
二、原因
mysql 5.6 版本后。默認啟用了ONLY_FULL_GROUP_BY。
ONLY_FULL_GROUP_BY是MySQL提供的一個sql_mode,通過這個sql_mode來提供SQL語句GROUP BY合法性的檢查。
http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_only_full_group_by
this is incompatible with sql_mode=only_full_group_by
這句話提示了這違背了mysql的規則,only fully group by,也就是說在執行的時候先分組,根據查詢的字段(select的字段)在分組的內容中取出,所以查詢的字段全部都應該在group by分組條件內;一種情況例外,查詢字段中如果含有聚合函數的字段不用包含在group by中,就像我上面的count(id)。
后來發現Order by排序條件的字段也必須要在group by內,排序的字段也是從分組的字段中取出。 不明白的可以去看一下。
三、解決方案
1、修改 sql-mode
修改文件 vim /etc/my.cnf.d/mysql-server.cnf
添加語句 sql-mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
注意還是那個面那個 sql-mode , 不是 sql_mode
注:網上很多說法是修改文件 vim /etc/my.cnf ,但是我這個不是,原因我也不知道,我是 yum 安裝的 mysql
2、重啟 mysqld
3、查詢 sql_mode
4、使用 group by 驗證
四、sql_mode
1、mysql5.0以后的三種模式
1)ANSI模式
寬松模式,更改語法和行為,使其更符合標准SQL。對插入數據進行校驗,如果不符合定義類型或長度,對數據類型調整或截斷保存,報warning警告。對於本文開頭中提到的錯誤,可以先把sql_mode設置為ANSI模式,這樣便可以插入數據,而對於除數為0的結果的字段值,數據庫將會用NULL值代替。
2)TRADITIONAL模式
嚴格模式,當向mysql數據庫插入數據時,進行數據的嚴格校驗,保證錯誤數據不能插入,報error錯誤,而不僅僅是警告。用於事物時,會進行事物的回滾。 注釋:一旦發現錯誤立即放棄INSERT/UPDATE。如果你使用非事務存儲引擎,這種方式不是你想要的,因為出現錯誤前進行的數據更改不會“滾動”,結果是更新“只進行了一部分”。
3)STRICT_TRANS_TABLES模式
嚴格模式,進行數據的嚴格校驗,錯誤數據不能插入,報error錯誤。如果不能將給定的值插入到事務表中,則放棄該語句。對於非事務表,如果值出現在單行語句或多行語句的第1行,則放棄該語句。
2、模式關鍵字
1)ONLY_FULL_GROUP_BY
對於GROUP BY聚合操作,如果在SELECT中的列、HAVING或者ORDER BY子句的列,沒有在GROUP BY中出現,那么這個SQL是不合法的。
2)NO_AUTO_VALUE_ON_ZERO
該值影響自增長列的插入。默認設置下,插入0或NULL代表生成下一個自增長值。如果用戶希望插入的值為0,該列又是自增長的,那么這個選項就有用了。
3)STRICT_TRANS_TABLES
在該模式下,如果一個值不能插入到一個事物表中,則中斷當前的操作,對非事物表不做限制
4)NO_ZERO_IN_DATE
在嚴格模式,不接受月或日部分為0的日期。如果使用IGNORE選項,我們為類似的日期插入'0000-00-00'。在非嚴格模式,可以接受該日期,但會生成警告。
5)NO_ZERO_DATE
在嚴格模式,不要將 '0000-00-00'做為合法日期。你仍然可以用IGNORE選項插入零日期。在非嚴格模式,可以接受該日期,但會生成警告。
6)ERROR_FOR_DIVISION_BY_ZERO
在INSERT或UPDATE過程中,如果數據被零除,則產生錯誤而非警告。如 果未給出該模式,那么數據被零除時MySQL返回NULL
7)NO_AUTO_CREATE_USER
禁止GRANT創建密碼為空的用戶
8)NO_ENGINE_SUBSTITUTION
如果需要的存儲引擎被禁用或未編譯,那么拋出錯誤。不設置此值時,用默認的存儲引擎替代,並拋出一個異常
9)PIPES_AS_CONCAT
將"||"視為字符串的連接操作符而非或運算符,這和Oracle數據庫是一樣的,也和字符串的拼接函數Concat相類似
10)ANSI_QUOTES
啟用ANSI_QUOTES后,不能用雙引號來引用字符串,因為它被解釋為識別符
3、sql_mode 設置
1)各種級別的 sql_mode
2)修改sql_mode
global級別:set global sql_mode='...'; (這里是修改的字段,所以 sql_mode , 不同於配置文件 的 sql-mode )
session級別:set session sql_mode=''...; (這里是修改的字段,所以 sql_mode , 不同於配置文件 的 sql-mode )
修改配置文件級別的就在上面的解決方案里面。