Mysql only_full_group_by以及其他關於sql_mode原因報錯詳細解決方案 網上太多相關資料,但是抄襲嚴重,有的講的也是之言片語的,根本不連貫(可能知道的人確實不想多說) 我總共花了3個多小時,反覆測試,總結一下 Mysql only_full_group_by以及其他關於sq ...
Mysql only_full_group_by以及其他關於sql_mode原因報錯詳細解決方案
網上太多相關資料,但是抄襲嚴重,有的講的也是之言片語的,根本不連貫(可能知道的人確實不想多說)
我總共花了3個多小時,反覆測試,總結一下
報錯信息:
1.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 with sql_mode=only_full_group_by
原因:
1.mysql 5.7中的sql_mode的值為:2.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.我的mysql5.7部署在linux上的,然後我使用navicat 12連接的,就說怎麼使用navicat 12查看吧2.使用navicat 打開資料庫,然後工具-->命令列界面 (快捷方式F6)3.然後輸入:SELECT @@sql_mode;4.看到值為:5.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:
1.我所使用的mysql運行時指定的配置如下:2./apps/mysql5.7.18/bin/mysqld --defaults-file=/apps/my3306.cnf --basedir=/apps/mysql5.7.18 --datadir=/apps/mysql/data/3306 --plugin-dir=/apps/mysql5.7.18/lib/mysql/plugin --user=mysql --log-error=/apps/mysql/data/3306/BJ-DYC-VM-5-106.err --open-files-limit=8192 --pid-file=/apps/mysql/data/3306/BJ-DYC-VM-5-106.pid --socket=/tmp/mysql_3306.sock --port=33063.4.那麼我修改的是/apps/my3306.cnf,你沒意見吧哈哈5.找到:6.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"7.8.修改為:9.sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"10.11.因為修改了mysql配置文件,所以重新啟動mysql12./apps/mysql5.7.18/bin/mysqld --defaults-file=/apps/my3306.cnf --basedir=/apps/mysql5.7.18 --datadir=/apps/mysql/data/3306 --plugin-dir=/apps/mysql5.7.18/lib/mysql/plugin --user=mysql --log-error=/apps/mysql/data/3306/BJ-DYC-VM-5-106.err --open-files-limit=8192 --pid-file=/apps/mysql/data/3306/BJ-DYC-VM-5-106.pid --socket=/tmp/mysql_3306.sock --port=3306
驗證一下:
1.進入命令列界面2.然後輸入:SELECT @@sql_mode;3.看到值為:4.STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION5.6.至此,你不用遵守:如下約定了:7. 對於GROUP BY聚合操作,如果在SELECT中的列,沒有在GROUP BY中出現,那麼這個SQL是不合法的,因為列不在GROUP BY從句中,所以對於設置了這個mode的資料庫,在使用group by 的時候,就要用MAX(),SUM(),ANT_VALUE()這種聚合函數,才能完成GROUP BY 的聚合操作。
解決辦法2
1.第二種辦法不用修改配置文件,使用navicat修改2.進入命令行界面(F6)3.輸入:SELECT @@GLOBAL.sql_mode;4.結果: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_SUBSTITUTION5.6.然後我們來修改sql_mode7.輸入: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 ';8.9.再運行你的sql:10.SELECT11. id,ip12.FROM13. ip_meta_backup14.GROUP BY15. ip16.HAVING17. count(ip) > 118.*****恭喜你,成功了*****19.20.21.22.然後你再運行你的sql是不是可以運行啦23.24.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';25.26.SELECT @@GLOBAL.sql_mode;
解決辦法3
1.第三種辦法不用修改配置文件,使用navicat修改2.進入命令行界面(F6)3.輸入:SELECT @@sql_mode; 註意:這邊預設了session,完整的是:SELECT @@SESSION.sql_mode;4.結果: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_SUBSTITUTION5.6.然後我們來修改sql_mode7.輸入: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 ';8.9.再運行你的sql:10.SELECT11. id,ip12.FROM13. ip_meta_backup14.GROUP BY15. ip16.HAVING17. count(ip) > 118.*****還是報only_full_group_by錯*****19.20.##############解決方法###################21.22.在你查詢的語句之前set sql_mode23.24.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 ';25.SELECT26. id,ip27.FROM28. ip_meta_backup29.GROUP BY30. ip31.HAVING32. count(ip) > 133.以後再新建查詢(包含group by)語句也不用再加set sql_mode 直到你關閉這次連接為止34.35.36.37.38.然後你再運行你的sql是不是可以運行啦39.40.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';41.42.SELECT @@GLOBAL.sql_mode;
對於辦法3解決的解釋
1.其實講第三種方法的時候說過SELECT @@sql_mode; 其實這邊預設了session,完整的是:SELECT @@SESSION.sql_mode;2.SESSION是當前會話的意思---->這句話就解釋了直到你關閉這次連接為止3.4.那為什麼在命令行set sql_mode,然後再新建查詢還是沒用呢?5.其實你只要在新建查詢中輸入SELECT @@sql_mode;你會發現你在命令行中的設置並沒有生效6.所以,我們只能重新在這次連接(會話)的新建查詢中重新set sql_mode,之後這次連接(這次會話)不再需要7.這一段語言解釋了“在你查詢的語句之前set sql_mode”這句話
對辦法2辦法3兩種方法的說明
1.這兩種set sql_mode方法,都會隨著在我部署linux上的mysql重啟而恢復到我指定的配置文件的my.cnf裡面設置的sql-mode選項中的內容2.這句話比較繞3.意思就是:linux上的mysql重啟後,你在navicat上設置的就不再有效,而是依據你指定的配置文件中的設定,就是my.cnf這個文件中設定
附上其他mode解釋
1.STRICT_TRANS_TABLES: 在該模式下,如果一個值不能插入到一個事務表中,則中斷當前的操作,對非事務表不做限制2.3.NO_ZERO_IN_DATE: 在嚴格模式下,不允許日期和月份為零4.5.NO_ZERO_DATE: 設置該值,mysql資料庫不允許插入零日期,插入零日期會拋出錯誤而不是警告。6.7.ERROR_FOR_DIVISION_BY_ZERO:在INSERT或UPDATE過程中,如果數據被零除,則產生錯誤而非警告。如 果未給出該模式,那麼數據被零除時MySQL返回NULL8.9.NO_AUTO_CREATE_USER: 禁止GRANT創建密碼為空的用戶10.11.NO_ENGINE_SUBSTITUTION: 如果需要的存儲引擎被禁用或未編譯,那麼拋出錯誤。不設置此值時,用預設的存儲引擎替代,並拋出一個異常12.13.PIPES_AS_CONCAT: 將"||"視為字元串的連接操作符而非或運算符,這和Oracle資料庫是一樣的,也和字元串的拼接函數Concat相類似14.15.ANSI_QUOTES: 啟用ANSI_QUOTES後,不能用雙引號來引用字元串,因為它被解釋為識別符16.17.NO_AUTO_VALUE_ON_ZERO: 該值影響自增長列的插入。預設設置下,插入0或NULL代表生成下一個自增長值。如果用戶 希望插入的值為0,而該列又是自增長的,那麼這個選項就有用了。
對於其他mode說明
1.其他的mode使用也無外乎更改配置文件,或者獨立更改(也就是方法2和3)