第二篇文章測(cè)試說(shuō)明
開(kāi)發(fā)測(cè)試中,難免會(huì)存在一些重復(fù)行數(shù)據(jù),因此常常會(huì)造成一些測(cè)試異常.
下面簡(jiǎn)單測(cè)試mysql表刪除重復(fù)數(shù)據(jù)行的相關(guān)操作.
主要通過(guò)一下三個(gè)大標(biāo)題來(lái)測(cè)試說(shuō)明:
02.嘗試刪除dept_name重復(fù)的列
03 嘗試刪除多個(gè)字段(dept_name和db_source)都重復(fù)的字段!
04 是否可以使用兩重for循環(huán)來(lái)判斷是否存在重復(fù)行并進(jìn)行刪除!
數(shù)據(jù)庫(kù)的表不要隨便刪除,需要?jiǎng)h除部分?jǐn)?shù)據(jù)的話請(qǐng)事先備份成SQL,或者創(chuàng)建備份表.不然--
后端一時(shí)爽,運(yùn)維火葬場(chǎng).
01.建表
(隨手找來(lái)一個(gè)現(xiàn)成的表,直接拷貝出sql語(yǔ)句)
CREATE DATABASE IF NOT EXISTS cloudDB01;
USE clouddb01;
CREATE TABLE IF NOT EXISTS `dept` (
`dept_no` BIGINT(20) NOT NULL AUTO_INCREMENT,
`dept_name` VARCHAR(60) DEFAULT NULL,
`db_source` VARCHAR(60) DEFAULT NULL,
PRIMARY KEY (`dept_no`)
) ENGINE=INNODB AUTO_INCREMENT=278 DEFAULT CHARSET=utf8;
/*插入dept表一系列數(shù)據(jù)*/
insert into `dept`(`dept_no`,`dept_name`,`db_source`) values
(1,'開(kāi)發(fā)部','clouddb01'),
(2,'人事部','clouddb01'),
(3,'財(cái)務(wù)部','clouddb01'),
(4,'市場(chǎng)部','clouddb01'),
(5,'運(yùn)維部','clouddb01'),
(6,'\'喝茶醬油部\'','clouddb01'),
(21,'開(kāi)發(fā)部','clouddb01'),
(22,'人事部','clouddb01'),
(23,'財(cái)務(wù)部','clouddb01'),
(24,'市場(chǎng)部','clouddb01'),
(25,'運(yùn)維部','clouddb01'),
(26,'\'喝茶醬油部\'','clouddb01');
02.嘗試刪除dept_name重復(fù)的列
也就是說(shuō),一個(gè)部門(mén)名只用占一行就可以了,多行的話豈不是浪費(fèi)了!
- 02.1.1.查詢(xún)存在dept_name存在重復(fù)的行
SELECT d.dept_name
FROM `dept` d
GROUP BY d.`dept_name`
HAVING COUNT(dept_name) > 1
-
02.1.2.結(jié)果
image.png - 02.2.1 把上面的表當(dāng)做子表查出重復(fù)的整個(gè)行
SELECT *
FROM `dept`
WHERE `dept_name` IN
(
SELECT d.dept_name
FROM `dept` d
GROUP BY d.`dept_name`
HAVING COUNT(dept_name) > 1
);
-
02.2.2 結(jié)果 (其實(shí)這里恰好就是整個(gè)表了)
image.png - 02.3.1 上面的結(jié)果是不行的,刪除時(shí)不能都刪了,我們?yōu)榱吮A粢粋€(gè)行,where條件需要再修改一下保留部門(mén)號(hào)(dept_no)最小的那行數(shù)據(jù)好了!
DELETE
FROM
`dept`
WHERE `dept_name` IN
(SELECT
dept_name
FROM
`dept`
GROUP BY `dept_name`
HAVING COUNT(dept_name) > 1)
AND `dept_no` NOT IN
(SELECT
MIN(dept_no)
FROM
`dept`
GROUP BY `dept_name`
HAVING COUNT(dept_name) > 1);
-
02.3.2 結(jié)果 : 執(zhí)行出現(xiàn)問(wèn)題;
image.png - 02.3.3 那是什么原因呢?原因:筆者的數(shù)據(jù)庫(kù)安全模式較高,為REPEATABLE-READ(可重復(fù)讀)級(jí)別,此模式下可以解決臟讀 和 不可重復(fù)讀 (mysql默認(rèn)的);
錯(cuò)誤代碼:1093,意思就是mysql不允許在查詢(xún)表的同時(shí)對(duì)這個(gè)表進(jìn)行刪除更新操作是不安全的.
image.png-
02.3.4 那可怎么辦?除了降級(jí)以外還能怎么辦?
Duang!!Duang!!Duang!!Duang!!
再來(lái)一個(gè)副本表"dept2",同時(shí)還可以起到備份的作用! 創(chuàng)建的sql在最上面,都在dept后面加個(gè)2即可!
dept2.png
-
-02.3.5 Show Time!是不是恍然大悟了!
DELETE
FROM
`dept`
WHERE `dept_name` IN
(SELECT
dept_name
FROM
`dept2`
GROUP BY `dept_name`
HAVING COUNT(dept_name) > 1)
AND `dept_no` NOT IN
(SELECT
MIN(dept_no)
FROM
`dept2`
GROUP BY `dept_name`
HAVING COUNT(dept_name) > 1);
-02.3.6 回頭看,不曾走遠(yuǎn),dept表中dept_name重復(fù)的行已經(jīng)沒(méi)了!!

03 嘗試刪除多個(gè)字段(dept_name和db_source)都重復(fù)的字段!
目的也就是一個(gè)部門(mén)實(shí)體用這兩個(gè)字段就可以清楚地區(qū)分出來(lái),如何任意兩行數(shù)據(jù)中存在dept_name和db_source都重復(fù)的話,那么必定有一項(xiàng)為重復(fù)的沒(méi)有意義的! 既然沒(méi)有意義,那就刪除了!
- 03.1.1 清空dept表和備份表dept2,dept表的sql如下,dept2的sql簡(jiǎn)單把下面的表名改一下即可
注意,人事部和喝茶醬油部這兩個(gè)的db_source列是油變動(dòng)的,不然跟上面的表就一模一樣了!
/*清空dept表,以及重置自增的主鍵*/
TRUNCATE dept;
/*插入dept表一系列數(shù)據(jù)*/
INSERT INTO `dept`(`dept_no`,`dept_name`,`db_source`) VALUES
(1,'開(kāi)發(fā)部','clouddb01'),
(2,'人事部','clouddb02'),
(3,'財(cái)務(wù)部','clouddb01'),
(4,'市場(chǎng)部','clouddb01'),
(5,'運(yùn)維部','clouddb01'),
(6,'\'喝茶醬油部\'','clouddb02'),
(21,'開(kāi)發(fā)部','clouddb01'),
(22,'人事部','clouddb01'),
(23,'財(cái)務(wù)部','clouddb01'),
(24,'市場(chǎng)部','clouddb01'),
(25,'運(yùn)維部','clouddb01'),
(26,'\'喝茶醬油部\'','clouddb01');
-
03.1.2 現(xiàn)有dept/dept2表數(shù)據(jù)
image.png - 03.2.1 比葫蘆畫(huà)瓢,使用上面的方法試試!同樣,如果存在兩個(gè)列數(shù)據(jù)重復(fù)的行的話,只保留dept_no最小的哪行數(shù)據(jù)!
DELETE
FROM
`dept`
WHERE `dept_name` IN
/*篩選出存在多列重復(fù)的*/
(SELECT
dept_name
FROM
`dept2`
GROUP BY `dept_name`,db_source
HAVING COUNT(dept_name) > 1)
/**保留dept_no最小的那行數(shù)據(jù)*/
AND `dept_no` NOT IN
(SELECT
MIN(dept_no)
FROM
`dept2`
GROUP BY `dept_name`
HAVING COUNT(dept_name) > 1);
-
03.2.2 結(jié)果怎么樣 : 符合預(yù)期結(jié)果
image.png- 03.3.1 單獨(dú)執(zhí)行第一個(gè)子表中的內(nèi)容,發(fā)現(xiàn)正好篩選出了四個(gè)部門(mén),沒(méi)有人事部和喝茶醬油部這兩個(gè).
想想,GROUP BY X, Y意思是將所有具有相同X字段值和Y字段值的記錄放到一個(gè)分組里。
這里的是 GROUP BYdept_name,db_source ,故只選出XY兩個(gè)字段都相同的才可以放到一塊來(lái).
image.png
- 03.3.1 單獨(dú)執(zhí)行第一個(gè)子表中的內(nèi)容,發(fā)現(xiàn)正好篩選出了四個(gè)部門(mén),沒(méi)有人事部和喝茶醬油部這兩個(gè).
04 是否可以使用兩重for循環(huán)來(lái)判斷是否存在重復(fù)行并進(jìn)行刪除!
- 就像一維數(shù)組一樣,進(jìn)行刪除操作!
- mysql貌似也支持寫(xiě)for循環(huán)!不過(guò).....用Java不更方便吧!
- 貌似還真可以, 先把所有mysql表中的數(shù)據(jù)取出來(lái)轉(zhuǎn)換成List<Entity>,然后跑兩重for循環(huán)遍歷List ,如果判斷出兩個(gè)實(shí)體符合重復(fù)的條件,則一定有一個(gè)實(shí)體是多余的,則從數(shù)據(jù)庫(kù)中移除對(duì)應(yīng)的記錄(行)即可!
- 暴力大法好! 時(shí)間上應(yīng)該不分上下!
- 我都想好了實(shí)現(xiàn)步驟,
1>取數(shù)據(jù): MybatisPlus的baseMapper.selectList() ;
2>for兩重判斷實(shí)體是否相等,
2> 如果存在則刪除一個(gè)即可: baseMapper.deleteById(xxxx) / 同時(shí)移除一個(gè)實(shí)體 兩個(gè)操作即可. - 其他方法也可以喲!
- 未完待續(xù)!!







