sql_mode= only_full_group_by的一點小故事

今天數據分析崗那邊的女同事問我:這個語句爲什麼報錯

報錯信息如下:

Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.t.mont' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

 

咋一看,這個SELECT語句的英文字段名咋這麼辣眼睛,好吧,原來是因爲這位小姐姐努力練習SQL語句,既然出了問題,作爲我們公司最慷(有)慨(空)的後端程序員,就幫她解答一下吧。

這個報錯信息是說:SELECT表達式查詢得到的結果  不在GROUP BY子句中,不兼容當前sql_mode爲only_full_group_by的模式,下面就趕緊來回憶一下sql_mode有哪些東西:

ONLY_FULL_GROUP_BY 對於GROUP BY聚合操作,如果在SELECT中的列,沒有在GROUP BY中出現,那麼將認爲這個SQL是不合法的,因爲列不在GROUP BY從句中
STRICT_TRANS_TABLES 在該模式下,如果一個值不能插入到一個事務表中,則中斷當前的操作,對非事務表不做任何限制
NO_ZERO_IN_DATE 在嚴格模式,不接受月或日部分爲0的日期。如果使用IGNORE選項,我們爲類似的日期插入'0000-00-00'。在非嚴格模式,可以接受該日期,但會生成警告。
NO_ZERO_DATE 在嚴格模式,不要將 '0000-00-00'做爲合法日期。你仍然可以用IGNORE選項插入零日期。在非嚴格模式,可以接受該日期,但會生成警告
ERROR_FOR_DIVISION_BY_ZERO 在嚴格模式,在INSERT或UPDATE過程中,如果被零除(或MOD(X,0)),則產生錯誤(否則爲警告)。如果未給出該模式,被零除時MySQL返回NULL。如果用到INSERT IGNORE或UPDATE IGNORE中,MySQL生成被零除警告,但操作結果爲NULL。
NO_AUTO_CREATE_USER 防止GRANT自動創建新用戶,除非還指定了密碼。
NO_ENGINE_SUBSTITUTION 如果需要的存儲引擎被禁用或未編譯,那麼拋出錯誤。不設置此值時,用默認的存儲引擎替代,並拋出一個異常。

 

如果select語句,MySQL允許查詢結果中  輸出的表達式是除聚集函數或group by column以外的表達式,這個表達式的值可能在經過group by操作後變成undefined。由於主流幾個數據庫廠家對SQL語意限制較爲嚴謹,所以像MySQL,sql_mode都是默認only_full_group_by的。這時候常用的解決方案有三種:一種是修改數據庫啓動的ini配置文件,第二種是用命令直接修改sql_mode,這兩種都暫時不能教她,萬一改錯東西或者時候忘記改回來,到時候測試的時候出現問題那可多麻煩,於是我教她第三種方法:根據報錯語句,把t.mont加到group by子句後面,於是乎,就這樣把問題解決了:

 

總結:ONLY_FULL_GROUP_BY的語義用於限定  select得出的結果集  語義必須明確,專業點說select得到的結果集,必須來自聚合函數(如sum函數)的結果,或者來自group by子句中的列。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章