今天我們來說下 mysql8 關于only_full_group_by的問題玲献,相信每個人在使用group by 函數時會突然跳出一個報錯信息:
ERROR?1055?(42000): Expression?#7?of?SELECT?list?is?not?in?GROUP?BY?clause?and?contains nonaggregated column?'postscan.verifyDelayLog.auditor'?which?is?not?functionally dependent?on?columns?in?GROUP?BY?clause; this?is?incompatible?withsql_mode=only_full_group_by
在mysql8.0以上的版本中只嚣,對于 group by 的這種聚合操作字柠,如果在select 中的列缕减,沒有在group by 中出現训枢,那么這個SQL是不合法的课兄,因為列不在group by的從句中鸟废,所以對于設置了這個mode的數據庫,在使用group?by?的時候卦绣,就要用MAX()耐量,SUM()飞蚓,ANT_VALUE()的這種聚合函數滤港,才能完成GROUP?BY?的聚合操作,那么話說回來了趴拧,如何關閉呢溅漾?
經過我們一番百度之后,獲取的結果是關于 only_full_group_by 著榴,但是按照教程所說添履,只要修改了my.cnf,
【
在my.cnf添加如下配置
[mysqld]
sql_mode='NO_AUTO_VALUE_ON_ZERO,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,PIPES_AS_CONCAT,ANSI_QUOTES'
】
配置文件加入相應參數[以下會講到]脑又,重啟的時候暮胧,依然差強人意,甚至給出教程的人并沒有親力親為的去測試问麸,就張貼了出來往衷,還會帶來新的mysql的報錯,或者是完全啟動報錯严卖,今天我就來詳細與大家一一說明這些參數席舍,及解決辦法。
sql_mode這個變量哮笆,很容易被忽視来颤,默認值是空值,在這種設置下是可以允許一些非法操作的稠肘,比如允許一些非法數據的插入福铅。在生產環(huán)境必須將這個值設置為嚴格模式,所以開發(fā)项阴、測試環(huán)境的數據庫也必須要設置本讥,這樣在開發(fā)測試階段就可以發(fā)現問題。
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創(chuàng)建密碼為空的用戶
NO_ENGINE_SUBSTITUTION:如果需要的存儲引擎被禁用或未編譯谦絮,那么拋出錯誤题诵。不設置此值時,用默認的存儲引擎替代层皱,并拋出一個異常
PIPES_AS_CONCAT:將"||"視為字符串的連接操作符而非或運算符性锭,這和Oracle數據庫是一樣的,也和字符串的拼接函數Concat相類似
ANSI_QUOTES:啟用ANSI_QUOTES后奶甘,不能用雙引號來引用字符串篷店,因為它被解釋為識別符
說明介紹完了,但是在8.0中這么設置下依然會報錯臭家,原因如下:
ERROR 1231 (42000): Variable 'sql_mode' can't be set to the value of 'NO_AUTO_CREATE_USER'
8.0以上已經取消了NO_AUTO_CREATE_USER這個關鍵字疲陕,刪掉sql語句中的這個關鍵字即可
最終,/etc/my.cnf 配置文件中? 修改? :sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'?
重啟mysql服務钉赁,大功告成蹄殃!~
在此,我給出另外兩種解決方案:
第二種辦法不用修改配置文件你踩,使用navicat修改
進入命令行界面
輸入: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
然后我們來修改sql_mode
set?GLOBAL?sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION ';
再運行你的sql诅岩,group by就可以使用了讳苦,但是這個方法不治本 ,當重啟mysql后吩谦,依然使用不了group by 所以鸳谜,第一種方法,是最有效的式廷。
第三種辦法不用修改配置文件咐扭,使用navicat修改
進入命令行界面
輸入:SELECT?@@sql_mode; 注意:這邊缺省了session,完整的是:SELECT?@@SESSION.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
然后我們來修改sql_mode
輸入:set?SESSION?sql_mode ='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION ';
再運行你的sql:
*****還是報only_full_group_by錯*****
##############解決方法###################
在你查詢的語句之前set?sql_mode
set?SESSION?sql_mode ='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION ';
以后再新建查詢(包含group?by)語句也不用再加set?sql_mode 直到你關閉這次連接為止
然后你再運行你的sql是不是可以運行啦
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';
SELECT?@@GLOBAL.sql_mode;
關于辦法3的解釋:
1.其實講第三種方法的時候說過SELECT?@@sql_mode; 其實這邊缺省了session,完整的是:SELECT?@@SESSION.sql_mode;
2.SESSION是當前會話的意思---->這句話就解釋了直到你關閉這次連接為止
3.那為什么在命令行set?sql_mode,然后再新建查詢還是沒用呢?
4.其實你只要在新建查詢中輸入SELECT?@@sql_mode;你會發(fā)現你在命令行中的設置并沒有生效
5.所以滑废,我們只能重新在這次連接(會話)的新建查詢中重新set?sql_mode,之后這次連接(這次會話)不再需要
6.這一段語言解釋了“在你查詢的語句之前set?sql_mode”這句話
對辦法2辦法3兩種方法的說明
1.這兩種set?sql_mode方法蝗肪,都會隨著在我部署linux上的mysql重啟而恢復到我指定的配置文件的my.cnf里面設置的sql-mode選項中的內容
2.這句話比較繞
3.意思就是:linux上的mysql重啟后,你在navicat上設置的就不再有效蠕趁,而是依據你指定的配置文件中的設定薛闪,就是my.cnf這個文件中設定
注:現在我將my.cnf列出來,供大家參考
未刪該設置的原版my.cnf內容:
[client]
port=3306
default-character-set=utf8
socket=/usr/local/mysql/mysql.sock
[mysql]
port=3306
default-character-set=utf8
socket=/usr/local/mysql/mysql.sock
[mysqld]
user=mysql
datadir=/usr/local/mysql/data
basedir=/usr/local/mysql
port=3306
max_connections = 1000
pid-file=/usr/local/mysql/mysqld.pid
socket=/usr/local/mysql/mysql.sock
server-id=1
default-authentication-plugin=mysql_native_password
sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'
# Disabling symbolic-links is recommended to prevent assorted security risks
#symbolic-links=0
# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under a different user or group,
# customize your systemd unit file for mariadb according to the
# instructions in http://fedoraproject.org/wiki/Systemd
#[mysqld_safe]
log-error=/var/log/mysql/error.log
#pid-file=/var/run/mariadb/mariadb.pid
#
# include all files from the config directory
#
!includedir /etc/my.cnf.d
default_authentication_plugin=mysql_native_password
server-id=201
log-bin=mysql-bin