一文带你了解mysql sql model的only_full_group_by模式含Error 1055问题分析
? ? ? ? ? ? ?Mysql only_full_group_by及Error 1055問題分析圖解
聲明
本文的數據來自網絡,部分代碼也有所參照,這里做了注釋和延伸,旨在技術交流,如有冒犯之處請聯系博主及時處理。
注: 1?員工表結構和數據初始化SQL腳本
? ? ? ? 2??當前驗證環境CentOS 8 X86 64、mysql 8.0.23、SQL Server 2019
問題描述
ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'trial.B.dname' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
編寫SQL時遇到如下錯誤,即出現錯誤 ERROR 1055,SELECT列表不在GROUP BY語句內且存在不函數依賴GROUP BY語句的非聚合字段'trial.B.dname',這是和sql_mode=only_full_group_by不兼容的(即不支持)。
解決方法
Way 1:臨時關閉only_full_group_by模式,這種方法通過修改系統變量,重啟數據庫后失效(修改后需要新開會話或者窗口)。首先查看下當前的sql_mode:
# 查看mysql當前的sql mode show VARIABLES LIKE 'sql_mode'; -- 1 對系統標量進行全局設置,但數據庫重啟后失效 set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'; -- 2 修改后需在新的回話(窗口)里驗證原SQL。Way 2: 永久關閉only_full_group_by模式,這種方法需要在mysql的配置文件里修改,然后重啟。
Step 1 找到配置文件/etc/my.cnf(或則關聯文件夾找到mysql-server.cnf)
Step 2: 在上述文件內的[mysqld]后追加
sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'
Step 3:保存配置文件后,重啟Mysql即可。
大話group by
啥,這就這么結束?!來來來,別走,我們來拉拉mysql的groupby和sql_mode only_full_group_by模式。開始之前我們得來先做個前期回顧。
SQL 92 group by
首先我們先了解下SQL92標準里關于group by的定義。
SQL-92?and?earlier?does?not?permit?queries?for?which?the?select?list,?HAVING?condition,?or?ORDER?BY?list?refer?to?nonaggregated?columns?that?are?not?named?in?the?GROUP?BY?clause.
簡單的說:SQL-92里 SELECT、HAVING、ORDER后的非聚合字段必須和GROUP BY后的字段保持完全一致。
來個例子瞧瞧唄?如下以sql server2019為例:
--正確的”姿勢” SELECT B.dname,B.deptno,MAX(sal) FROM emp A JOIN dept B ON A.deptno = B.deptno GROUP BY B.deptno,B.dname;--錯誤的“姿勢” SELECT B.dname,B.deptno,MAX(sal) FROM emp A JOIN dept B ON A.deptno = B.deptno GROUP BY B.deptno;SQL 99 group by
但是我們經常看到MYSQL的SELECT列表的字段并不在GROUP BY后,這又是咋回事?話不多說,先上幾個案例。
-- Msyql: -- Case 1(此腳本在sql server里報錯) SELECT B.deptno,B.dname,MAX(sal) FROM emp A JOIN dept B ON A.deptno = B.deptno GROUP BY B.deptno;但為什么mysql就能支持呢?
SQL:1999 and later permits such nonaggregates per optional feature T301 if they are functionally dependent on?GROUP BY?columns: If such a relationship exists between?name?and?custid, the query is legal. This would be the case, for example, were?custid?a primary key of?customers.
SQL 99登場,這里即是定義了新的標準,如果group by后面的字段是主鍵(唯一鍵),而且非聚合字段是函數依賴group by后字段的,那么可以將這些非聚合字段放在SELECT、HAVING、ORDER BY的語句之后。
MySQL implements detection of functional dependence. If the?ONLY_FULL_GROUP_BY?SQL mode is enabled (which it is by default), MySQL rejects queries for which the select list,?HAVING?condition, or?ORDER BY?list refer to nonaggregated columns that are neither named in the?GROUP BY?clause nor are functionally dependent on them.
Mysql 實現了這種檢測函數依賴,這時ONLY_FULL_GROUP_BY?SQL 模式登場,mysql里SQL mode設置了這種模式那么如果 group by后的不補全字段或是無函數依賴的字段時非聚合字段放在SELECT、HAVING、ORDER BY的語句之后是不支持的。
有點繞,我們直接開啟個案例來說明ONLY_FULL_GROUP_BY有何魔力。
啟用only_full_group_by模式
-- Case 2: SELECT B.dname,MAX(sal) FROM emp A JOIN dept B ON A.deptno = B.deptno GROUP BY B.loc原因分析,這里group by后的字段loc并沒有定義為主鍵或則唯一鍵,所以在sql mode是ONLY_FULL_GROUP_BY模式下報錯(即不支持)。
我們再來個簡單些的例子,即只涉及一張表。
-- Case 3: --Step 1 創建一張無主鍵、唯一鍵的表,插入4條記錄(id字段的值不重復)。 CREATE TABLE `test_04251019` (`id` int DEFAULT NULL,`name` varchar(10) DEFAULT NULL,`addr` varchar(12) DEFAULT NULL,`memo` varchar(40) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- Step 2 插入4條記錄 INSERT INTO `test_04251019` VALUES ('1', 'hanmeimie', 'Guangzhou', 'Fullbakup'); INSERT INTO `test_04251019` VALUES ('2', 'lilei', 'Guangzhou', 'in increament'); INSERT INTO `test_04251019` VALUES ('4', 'Tom', 'Shanghai', 'no more'); INSERT INTO `test_04251019` VALUES ('5', 'John', 'Shanghai', 'no more_5');-- Step 3 此時我們仿照Case 2寫個簡單點的聚合語句 SELECT name, MAX(LENGTH(addr)) FROM test_04251019 GROUP BY id; -- Case 4: -- Step 1 創建個表類似(test_04251019),但是id定義為主鍵 CREATE TABLE `test_04251019_key` (`id` int NOT NULL,`name` varchar(10) DEFAULT NULL,`addr` varchar(12) DEFAULT NULL,`memo` varchar(40) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;-- Step 2 插入數據(直接拷貝至test_04251019) INSERT INTO test_04251019_key(id,name,addr,memo) SELECT id,name,addr,memo FROM test_04251019; COMMIT;-- Step 3 新增個唯一字段id_2并更新數據 ALTER TABLE test_04251019_key ADD id_2 int NOT NULL; UPDATE test_04251019_key SET id_2 = 100+id; ALTER TABLE test_04251019_key ADD CONSTRAINT unique_id_2 UNIQUE(id_2);-- Step 4 驗證group by后含主鍵、唯一鍵,非聚合字段并存的情況 SELECT name, MAX(LENGTH(addr)) FROM test_04251019_key GROUP BY id; SELECT name, MAX(LENGTH(addr)) FROM test_04251019_key GROUP BY id_2;關閉only_full_group_by模式
一眼不合,我們就關閉only_full_group_by模式。那么我們就來關閉,這里通過修改系統變量的方式。
-- 通過修改系統變量方式,注意修改后需要在新的回話(重開個客戶端)里驗證 set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';show variables like 'sql_mode';這時我們來驗證Case 2
?Case 3
Case 4:追加案例,針對case 3,如果我們往test_04251019里插入一條記錄
-- 插入一條數據(這里id是重復的,已有等于5的了) INSERT INTO test_04251019 VALUES(5,'Jim','Shanghai2','no more_5_2');-- 再執行聚合函數驗證 SELECT name, MAX(LENGTH(addr)) FROM test_04251019 GROUP BY id;what?“Jim”那條記錄對應的GROUP BY統計去哪兒了?為啥不能是我?!
延展閱讀
ONLY_FULL_GROUP_BY下的特例(僅有聚合函數和WHERE,這里WHERE是必選項),詳見如下截圖:
總結
敲黑板
總結
以上是生活随笔為你收集整理的一文带你了解mysql sql model的only_full_group_by模式含Error 1055问题分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 烧烤食材去哪里买 推荐几家优质烧烤食材供
- 下一篇: linux cmake编译源码,linu