mysql duplicate key与replace into对比
【REDME】
有些業(yè)務(wù)場(chǎng)景如下:
對(duì)于數(shù)據(jù)已經(jīng)存在的,則更新;否則新增;
怎么判定數(shù)據(jù)已經(jīng)存在,通過(guò)主鍵或唯一索引來(lái)判斷;
業(yè)務(wù)場(chǎng)景:業(yè)務(wù)庫(kù)的全局參數(shù)表的參數(shù)值的新增或更新就是 有則更細(xì)無(wú)則插入的常見(jiàn)業(yè)務(wù)場(chǎng)景;
【1】2種實(shí)現(xiàn)方式
通常情況下,我們是先select,判斷數(shù)據(jù)是否存在;若不存在,則新增,否則更新;
要完成這個(gè)小小功能,我們需要寫(xiě)3條sql,非常麻煩;
采用2種簡(jiǎn)單方式(只需要寫(xiě)1條sql):
- 方式1, duplicate key, insert into ...... on duplicate key update ...
- 方式2,replace into,
【1.1】duplicate key update
0. duplicate 官方文檔翻譯,參見(jiàn)? ?https://blog.csdn.net/PacosonSWJTU/article/details/120058725
1.duplicate顧名思義,有重復(fù)鍵則更新,否則插入;
2.語(yǔ)法如下:
如果指定 ON DUPLICATE KEY UPDATE 子句并且要插入的行會(huì)導(dǎo)致 UNIQUE 索引或 PRIMARY KEY 中出現(xiàn)重復(fù)值,則會(huì)發(fā)生舊行的 UPDATE。 例如,如果列 a 聲明為 UNIQUE 并包含值 1,則以下兩個(gè)語(yǔ)句具有類(lèi)似的效果:
INSERT INTO t1 (a,b,c) VALUES (1,2,3)ON DUPLICATE KEY UPDATE c=c+1;UPDATE t1 SET c=c+1 WHERE a=1;3.測(cè)試案例
-- 表結(jié)構(gòu) CREATE TABLE `my_cust_warn_tbl` (`rcrd_id` varchar(64) NOT NULL COMMENT '記錄編號(hào)',`cust_num` varchar(50) NOT NULL COMMENT '客戶(hù)號(hào)',`cust_name` varchar(50) DEFAULT '' COMMENT '客戶(hù)姓名',`warn_times` int(11) DEFAULT NULL COMMENT '客戶(hù)預(yù)警次數(shù)',`create_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '創(chuàng)建時(shí)間',`last_modify_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '最后修改時(shí)間',PRIMARY KEY (`rcrd_id`),UNIQUE KEY `uni_cust_num` (`cust_num`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客戶(hù)預(yù)警表'注意: 使用duplicate語(yǔ)法的數(shù)據(jù)庫(kù)表一定要設(shè)置唯一索引,以便于判斷數(shù)據(jù)是否存在;
統(tǒng)計(jì)客戶(hù)的預(yù)警次數(shù),很顯然就是有著更新,沒(méi)有則新增;
INSERT INTO mybatis.my_cust_warn_tbl (rcrd_id, cust_num, cust_name, warn_times) VALUES('hand_11', 'hand_11_custnum', 'hand_11_custname', 0) on duplicate key update warn_times=warn_times+1, create_time = current_timestamp ;第一次執(zhí)行上述sql,由于 hand_11_cust 不存在,則返回條數(shù)是1;
?第二次執(zhí)行SQL如下 (注意,第一次與第二次的sql不一樣,主鍵不同,但客戶(hù)號(hào)相同,客戶(hù)號(hào)是唯一索引)
INSERT INTO mybatis.my_cust_warn_tbl (rcrd_id, cust_num, cust_name, warn_times) VALUES('hand_11_2', 'hand_11_custnum', 'hand_11_custname', 0) on duplicate key update warn_times=warn_times+1, create_time = current_timestamp ;由于 hand_11_cust 已經(jīng)存在,更新條數(shù)返回2;
【1.2】replace into
1.replace顧名思義,替換,有則先刪除,后插入;沒(méi)有則直接插入;
步驟為:
- step1)delete 存在的記錄(通過(guò)主鍵或唯一索引來(lái)判斷);
- step2)重新插入新值;
為了演示效果,我們新建了一個(gè)主鍵自增的數(shù)據(jù)庫(kù)表;
drop table if exists my_cust_warn_autopk_tbl ; CREATE TABLE `my_cust_warn_autopk_tbl` (`rcrd_id` int primary key not null auto_increment COMMENT '記錄編號(hào)',`cust_num` varchar(50) NOT NULL COMMENT '客戶(hù)號(hào)',`cust_name` varchar(50) DEFAULT '' COMMENT '客戶(hù)姓名',`warn_times` int(11) DEFAULT NULL COMMENT '客戶(hù)預(yù)警次數(shù)',`create_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '創(chuàng)建時(shí)間',`last_modify_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '最后修改時(shí)間',UNIQUE KEY `uni_cust_num` (`cust_num`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客戶(hù)預(yù)警表(自增)' ;2. 測(cè)試案例
REPLACE INTO mybatis.my_cust_warn_autopk_tbl (cust_num, cust_name, warn_times) VALUES('hand_12_custnum', 'hand_12_custname', 0) ;因?yàn)橹皼](méi)有存在的數(shù)據(jù),故更新行數(shù)為1;
?剛剛插入的記錄的主鍵值為1 ; 如下;
?接著, 我們把客戶(hù)姓名字段設(shè)置為null看下; 發(fā)現(xiàn)更新行數(shù)為2;
REPLACE INTO mybatis.my_cust_warn_autopk_tbl (cust_num, cust_name, warn_times) VALUES('hand_12_custnum', null, 0) ;我們看下數(shù)據(jù)長(zhǎng)什么樣子:僅有一個(gè) 主鍵值為2的記錄存在;
很顯然,因?yàn)榇嬖诳蛻?hù)號(hào)為 hand_12_custnum的記錄,于是先刪除了 主鍵為1的記錄,然后再插入主鍵為2的記錄,如下:
?當(dāng)然了,通過(guò)兩次sql的 create_time 也可以判斷出 第2次replace是 刪除舊記錄,然后重新新增一條數(shù)據(jù),而不是在舊記錄上修改; 因?yàn)?兩次的create_time 不一樣;
【2】 兩者執(zhí)行時(shí)間簡(jiǎn)單對(duì)比
show variables like "%pro%"; set profiling=1; show profiles ;總結(jié)
以上是生活随笔為你收集整理的mysql duplicate key与replace into对比的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 三星i939电信版(三星i509电信版)
- 下一篇: (转)mysql查看连接客户端ip和杀死