一文带你了解mysql sql model的only_full_group_by模式含Error 1055问题分析
? ? ? ? ? ? ?Mysql only_full_group_by及Error 1055問(wèn)題分析圖解
聲明
本文的數(shù)據(jù)來(lái)自網(wǎng)絡(luò),部分代碼也有所參照,這里做了注釋和延伸,旨在技術(shù)交流,如有冒犯之處請(qǐng)聯(lián)系博主及時(shí)處理。
注: 1?員工表結(jié)構(gòu)和數(shù)據(jù)初始化SQL腳本
? ? ? ? 2??當(dāng)前驗(yàn)證環(huán)境CentOS 8 X86 64、mysql 8.0.23、SQL Server 2019
問(wèn)題描述
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
編寫(xiě)SQL時(shí)遇到如下錯(cuò)誤,即出現(xiàn)錯(cuò)誤 ERROR 1055,SELECT列表不在GROUP BY語(yǔ)句內(nèi)且存在不函數(shù)依賴(lài)GROUP BY語(yǔ)句的非聚合字段'trial.B.dname',這是和sql_mode=only_full_group_by不兼容的(即不支持)。
解決方法
Way 1:臨時(shí)關(guān)閉only_full_group_by模式,這種方法通過(guò)修改系統(tǒng)變量,重啟數(shù)據(jù)庫(kù)后失效(修改后需要新開(kāi)會(huì)話(huà)或者窗口)。首先查看下當(dāng)前的sql_mode:
# 查看mysql當(dāng)前的sql mode show VARIABLES LIKE 'sql_mode'; -- 1 對(duì)系統(tǒng)標(biāo)量進(jìn)行全局設(shè)置,但數(shù)據(jù)庫(kù)重啟后失效 set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'; -- 2 修改后需在新的回話(huà)(窗口)里驗(yàn)證原SQL。Way 2: 永久關(guān)閉only_full_group_by模式,這種方法需要在mysql的配置文件里修改,然后重啟。
Step 1 找到配置文件/etc/my.cnf(或則關(guān)聯(lián)文件夾找到mysql-server.cnf)
Step 2: 在上述文件內(nèi)的[mysqld]后追加
sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'
Step 3:保存配置文件后,重啟Mysql即可。
大話(huà)group by
啥,這就這么結(jié)束?!來(lái)來(lái)來(lái),別走,我們來(lái)拉拉mysql的groupby和sql_mode only_full_group_by模式。開(kāi)始之前我們得來(lái)先做個(gè)前期回顧。
SQL 92 group by
首先我們先了解下SQL92標(biāo)準(zhǔn)里關(guān)于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.
簡(jiǎn)單的說(shuō):SQL-92里 SELECT、HAVING、ORDER后的非聚合字段必須和GROUP BY后的字段保持完全一致。
來(lái)個(gè)例子瞧瞧唄?如下以sql server2019為例:
--正確的”姿勢(shì)” SELECT B.dname,B.deptno,MAX(sal) FROM emp A JOIN dept B ON A.deptno = B.deptno GROUP BY B.deptno,B.dname;--錯(cuò)誤的“姿勢(shì)” 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
但是我們經(jīng)??吹組YSQL的SELECT列表的字段并不在GROUP BY后,這又是咋回事?話(huà)不多說(shuō),先上幾個(gè)案例。
-- Msyql: -- Case 1(此腳本在sql server里報(bào)錯(cuò)) 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登場(chǎng),這里即是定義了新的標(biāo)準(zhǔn),如果group by后面的字段是主鍵(唯一鍵),而且非聚合字段是函數(shù)依賴(lài)group by后字段的,那么可以將這些非聚合字段放在SELECT、HAVING、ORDER BY的語(yǔ)句之后。
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 實(shí)現(xiàn)了這種檢測(cè)函數(shù)依賴(lài),這時(shí)ONLY_FULL_GROUP_BY?SQL 模式登場(chǎng),mysql里SQL mode設(shè)置了這種模式那么如果 group by后的不補(bǔ)全字段或是無(wú)函數(shù)依賴(lài)的字段時(shí)非聚合字段放在SELECT、HAVING、ORDER BY的語(yǔ)句之后是不支持的。
有點(diǎn)繞,我們直接開(kāi)啟個(gè)案例來(lái)說(shuō)明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并沒(méi)有定義為主鍵或則唯一鍵,所以在sql mode是ONLY_FULL_GROUP_BY模式下報(bào)錯(cuò)(即不支持)。
我們?cè)賮?lái)個(gè)簡(jiǎn)單些的例子,即只涉及一張表。
-- Case 3: --Step 1 創(chuàng)建一張無(wú)主鍵、唯一鍵的表,插入4條記錄(id字段的值不重復(fù))。 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 此時(shí)我們仿照Case 2寫(xiě)個(gè)簡(jiǎn)單點(diǎn)的聚合語(yǔ)句 SELECT name, MAX(LENGTH(addr)) FROM test_04251019 GROUP BY id; -- Case 4: -- Step 1 創(chuàng)建個(gè)表類(lèi)似(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 插入數(shù)據(jù)(直接拷貝至test_04251019) INSERT INTO test_04251019_key(id,name,addr,memo) SELECT id,name,addr,memo FROM test_04251019; COMMIT;-- Step 3 新增個(gè)唯一字段id_2并更新數(shù)據(jù) 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 驗(yàn)證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;關(guān)閉only_full_group_by模式
一眼不合,我們就關(guān)閉only_full_group_by模式。那么我們就來(lái)關(guān)閉,這里通過(guò)修改系統(tǒng)變量的方式。
-- 通過(guò)修改系統(tǒng)變量方式,注意修改后需要在新的回話(huà)(重開(kāi)個(gè)客戶(hù)端)里驗(yàn)證 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';這時(shí)我們來(lái)驗(yàn)證Case 2
?Case 3
Case 4:追加案例,針對(duì)case 3,如果我們往test_04251019里插入一條記錄
-- 插入一條數(shù)據(jù)(這里id是重復(fù)的,已有等于5的了) INSERT INTO test_04251019 VALUES(5,'Jim','Shanghai2','no more_5_2');-- 再執(zhí)行聚合函數(shù)驗(yàn)證 SELECT name, MAX(LENGTH(addr)) FROM test_04251019 GROUP BY id;what?“Jim”那條記錄對(duì)應(yīng)的GROUP BY統(tǒng)計(jì)去哪兒了?為啥不能是我?!
延展閱讀
ONLY_FULL_GROUP_BY下的特例(僅有聚合函數(shù)和WHERE,這里WHERE是必選項(xiàng)),詳見(jiàn)如下截圖:
總結(jié)
敲黑板
總結(jié)
以上是生活随笔為你收集整理的一文带你了解mysql sql model的only_full_group_by模式含Error 1055问题分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 烧烤食材去哪里买 推荐几家优质烧烤食材供
- 下一篇: Mysql备份工具xtrabackup