insert...on?duplicate?key?update語法詳解
一.作用和使用場景
在mysql入庫時,不能出現(xiàn)兩條數(shù)據(jù)主鍵一致的情況,因為在兩條數(shù)據(jù)的主鍵一致的情況下,mysql就會判定為待插入數(shù)據(jù)在數(shù)據(jù)庫中存在重復(fù)數(shù)據(jù),也就是說判斷數(shù)據(jù)是否重復(fù)是根據(jù)主鍵來區(qū)別的。
但是有一些場景,如日志文件解析入庫,消息隊列接收數(shù)據(jù)入庫等情況下可能解析到或者接收到待插入的重復(fù)數(shù)據(jù)存在重復(fù)數(shù)據(jù)則更新,不存在則插入。
這時如下語句的寫法就派上用場了,on duplicate key update的作用也就是說存在重復(fù)數(shù)據(jù)則更新,不存在則插入。
二.例子詳細(xì)講解
場景大概是這樣的,業(yè)務(wù)方的需求是查詢一條語句在不在,如果在就給出一個update語句,更新這條記錄,如果不在,就給出一個insert語句,插入這條記錄。邏輯大概是:
result = select * from table; if result = 0 insert the record into table; else update the record;
這樣的操作乍一看沒有什么問題,但是仔細(xì)分析分析,還是有些瓶頸的,目前來看,我能分析到的瓶頸有兩個,
其一:
每次要執(zhí)行2個SQL,效率比較差;
其二:
當(dāng)我們在高并發(fā)的情況下跑這條語句,如果程序崩潰,不能保證操作的原子性。
說明: 1. on duplicate key update 含義: 1)如果在INSERT語句末尾指定了 on duplicate key update, 并且插入行后會導(dǎo)致在一個UNIQUE索引或PRIMARY KEY中出現(xiàn)重復(fù)值, 則在出現(xiàn)重復(fù)值的行執(zhí)行UPDATE; 2)如果不會導(dǎo)致唯一值列重復(fù)的問題,則插入新行。 2. values(col_name)函數(shù)只是取當(dāng)前插入語句中的插入值,并沒有累加功能。 如:count = values(count) 取前面 insert into 中的 count 值,并更新 當(dāng)有多條記錄沖突,需要插入時,前面的更新值都被最后一條記錄覆蓋, 所以呈現(xiàn)出取最后一條更新的現(xiàn)象。 如:count = count + values(count) 依然取前面 insert into 中的 count 值, 并與原記錄值相加后更新回數(shù)據(jù)庫,這樣,當(dāng)多條記錄沖突需要插入時, 就實現(xiàn)了不斷累加更新的現(xiàn)象。 注:insert into ... on duplicate key update ... values() 這個語句 盡管在沖突時執(zhí)行了更新,并沒有插入,但是發(fā)現(xiàn)依然會占用 id 序號(自增), 出現(xiàn)很多丟失的 id 值,可參看下面案例
函數(shù)使用說明:在一個 INSERT … ON DUPLICATE KEY UPDATE … 語句中,你可以在 UPDATE 子句中使用 VALUES(col_name ) 函數(shù),用來訪問來自該語句的 INSERT 部分的列值。換言之,UPDATE 子句中的 VALUES(col_name ) 訪問需要被插入的 col_name 的值 , 并不會發(fā)生重復(fù)鍵沖突。這個函數(shù)在多行插入中特別有用。 VALUES() 函數(shù)只在 INSERT ... UPDATE 語句中有意義,而在其它情況下只會返回 NULL。
**案例: 0. 創(chuàng)建案例表 word_count_0626(單詞計數(shù)表) use test; CREATE TABLE IF NOT EXISTS word_count_0626 ( id int(11) NOT NULL AUTO_INCREMENT, word varchar(64) NOT NULL, count int(11) DEFAULT 0, date date NOT NULL, PRIMARY KEY (id), UNIQUE KEY word (word, date) // (word,date) 兩字段組合唯一 ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 注:curdate() 為 "2019-06-26" 1. 執(zhí)行第一次:(首次數(shù)據(jù)庫表中沒有數(shù)據(jù),正常插入) insert into word_count_0626 (word, count, date) values ('a',5,curdate()) on duplicate key update count=values(count); # 結(jié)果顯示: id word count date 1 a 5 2019-06-26 2. 執(zhí)行第二次:(與第一次的唯一(word,date)沖突,執(zhí)行更新) insert into word_count_0626 (word, count, date) values ('a',6,curdate()) on duplicate key update count=values(count); # 結(jié)果顯示: id word count date 1 a 6 2019-06-26 (更新) 3. 執(zhí)行第三次: insert into word_count_0626 (word, count, date) values ('a',6,curdate()-1), // 取前一天,不會沖突 ('a',7,curdate()) // 沖突 on duplicate key update count=values(count); # 結(jié)果顯示: id word count date 1 a 7 2019-06-26 (更新) 3 a 6 2019-06-25 (新插入) 4. 執(zhí)行第四次:(更新沖突的最后一條插入值) insert into word_count_0626 (word, count, date) values ('a',2,curdate()), // 沖突 ('a',1,curdate()) // 沖突 on duplicate key update count=values(count); # 結(jié)果顯示: id word count date 1 a 1 2019-06-26 (更新最后一條插入值) 3 a 6 2019-06-25 (不變) 5. 執(zhí)行第五次:(更新沖突的累加插入值) insert into word_count_0626 (word, count, date) values ('a',2,curdate()), ('a',1,curdate()) on duplicate key update count=count+values(count); // 實現(xiàn)每行累加 # 結(jié)果顯示: id word count date 1 a 4 2019-06-26 3 a 6 2019-06-25 6. 執(zhí)行第六次:(無沖突插入,觀察 id 鍵值,出現(xiàn)了很多丟失,id 直接跳到了 9) insert into word_count_0626 (word, count, date) values ('b',2,curdate()) on duplicate key update count=count+values(count); # 結(jié)果顯示: id word count date 1 a 4 2019-06-26 3 a 6 2019-06-25 9 b 2 2019-06-26
說明:
insert...on duplicate key方法
簡單寫一個例子,內(nèi)容大致如下:
1、首先創(chuàng)建一個包含id,name,age的表,其中id是主鍵;
2、在這個表中插入一條id=1的記錄;
3、使用insert...on duplicate key update語法插入一條id=2的記錄;
4、使用同樣的語法更新id=1的記錄;
mysql 23:12:32>>create table test_1( -> id int primary key auto_increment, -> name varchar(20), -> age int not null -> ) engine=innodb charset=utf8; Query OK, 0 rows affected (0.08 sec) mysql 23:13:26>>insert into test_1 values (1,'yyz',16); Query OK, 1 row affected (0.01 sec) mysql 23:13:58>>select * from test_1; +----+------+-----+ | id | name | age | +----+------+-----+ | 1 | yyz | 16 | +----+------+-----+ 1 row in set (0.00 sec) mysql 23:14:36>>insert into test_1 (id,name,age) values (2,'yyz',18) on duplicate key update age=18; Query OK, 1 row affected (0.01 sec) mysql 23:15:08>>select * from test_1; +----+------+-----+ | id | name | age | +----+------+-----+ | 1 | yyz | 16 | | 2 | yyz | 18 | +----+------+-----+ 2 rows in set (0.00 sec) mysql 23:15:17>>insert into test_1 (id,name,age) values (1,'yyz',18) on duplicate key update age=18; Query OK, 2 rows affected (0.00 sec) mysql 23:15:28>>select * from test_1; +----+------+-----+ | id | name | age | +----+------+-----+ | 1 | yyz | 18 | | 2 | yyz | 18 | +----+------+-----+ 2 rows in set (0.00 sec)
insert...on duplicate key update語法的作用,可以分析到,當(dāng)發(fā)生主鍵沖突的時候,可以直接進行update操作,這個update操作里面可以更新任意想要更新的列;而沒有主鍵沖突的時候,相當(dāng)于對這個表進行了一次插入操作。
Replace操作
Replace語句。使用Replace插入一條記錄時,如果不重復(fù),Replace就和Insert的功能一樣,如果有重復(fù)記錄,Replace就使用新記錄的值來替換原來的記錄值。
使用REPLACE的最大好處就是可以將Delete和Insert合二為一,形成一個原子操作。這樣就可以不必考慮在同時使用Delete和Insert時添加事務(wù)等復(fù)雜操作了。
在使用Replace時,表中必須有唯一索引,而且這個索引所在的字段不能允許空值,否則Replace就和Insert完全一樣的。
在執(zhí)行Replace后,系統(tǒng)返回了所影響的行數(shù),如果返回1,說明在表中并沒有重復(fù)的記錄,如果返回2,說明有一條重復(fù)記錄,系統(tǒng)自動先調(diào)用了Delete刪除這條記錄,然后再記錄用Insert來插入這條記錄。
不同之處
有了上面的知識儲備,這兩條命令的不同之處就顯而易見了,replace是刪除記錄,然后再重新insert,而insert...on duplicate key update是直接在該條記錄上修改,所以二者的差別主要有以下兩處:
1、當(dāng)表中存在自增值的時候,如果表中存在某條記錄,replace語法會導(dǎo)致自增值+1,而insert...on duplicate key update語法不會;
2、當(dāng)表中的某些字段中包含默認(rèn)值的時候,replace操作插入不完全字段的記錄,會導(dǎo)致其他字段直接使用默認(rèn)值,而insert...on duplicate key update操作會保留該條記錄的原有值。
到此這篇關(guān)于insert...on duplicate key update語法詳解的文章就介紹到這了,更多相關(guān)insert...on duplicate key update 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- mysql 中 replace into 與 insert into on duplicate key update 的用法和不同點實例分析
- MySQL的Replace into 與Insert into on duplicate key update真正的不同之處
- insert into … on duplicate key update / replace into 多行數(shù)據(jù)介紹
- Mysql中Insert into xxx on duplicate key update問題
- mysql insert的幾點操作(DELAYED,IGNORE,ON DUPLICATE KEY UPDATE )
相關(guān)文章
簡單了解MySQL數(shù)據(jù)庫優(yōu)化技巧
這篇文章主要介紹了簡單了解MySQL數(shù)據(jù)庫優(yōu)化技巧,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07Slave memory leak and trigger oom-killer
這篇文章主要介紹了Slave memory leak and trigger oom-killer,需要的朋友可以參考下2016-07-07MySQL查詢優(yōu)化:LIMIT 1避免全表掃描提高查詢效率
在某些情況下,如果明知道查詢結(jié)果只有一個,SQL語句中使用LIMIT 1會提高查詢效率,感興趣的朋友可以了解下哈,希望對你優(yōu)化mysql查詢有所幫助2013-04-04mysql 5.7.21解壓版安裝配置方法圖文教程(win10)
這篇文章主要為大家詳細(xì)介紹了win10下mysql 5.7.21解壓版安裝配置方法圖文教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-02-02mysql中l(wèi)imit查詢踩坑實戰(zhàn)記錄
在MySQL中我們常常用order by來進行排序,使用limit來進行分頁,下面這篇文章主要給大家介紹了關(guān)于mysql中l(wèi)imit查詢踩坑的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-03-03