Mysql中INSERT ... ON DUPLICATE KEY UPDATE的實踐

一、前言

在日常業(yè)務(wù)開發(fā)中經(jīng)常有這樣一個場景,首先創(chuàng)建一條記錄,然后插入到數(shù)據(jù)庫;如果數(shù)據(jù)庫已經(jīng)存在同一主鍵的記錄,則執(zhí)行update操作,如果不存在,則執(zhí)行insert操作;

這個操作可以在業(yè)務(wù)層做,也可以在數(shù)據(jù)庫層面做;

業(yè)務(wù)層一般做法是先查詢,如果不存在在插入,如果存在則更新,但是查詢和插入不是原子性操作,在并發(fā)量比較高的時候,可能兩個線程都查詢某個記錄不存在,所以會執(zhí)行兩次插入,然后其中一條必然會因為主鍵(這里說的主鍵不是遞增主鍵)沖突而失敗。

數(shù)據(jù)庫層mysql中INSERT ... ON DUPLICATE KEY UPDATE就可以做這個事情,并且是原子性操作,本文就來講解的使用。

二、INSERT ... ON DUPLICATE KEY UPDATE命令

2.1單條記錄下使用


INSERT INTO t1 (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=c+1;

如上sql假如t1表的主鍵或者UNIQUE 索引是a,那么當(dāng)執(zhí)行上面sql時候,如果數(shù)據(jù)庫里面已經(jīng)存在a=1的記錄則更新這條記錄的c字段的值為原來值+1,然后返回值為2。如果不存在則插入a=1,b=2,c=3到數(shù)據(jù)庫,然后返回值為1。

2.2多記錄下使用

INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6)
  ON DUPLICATE KEY UPDATE c=VALUES(c);

三、MyBatis下使用

Mybatis作為經(jīng)典的數(shù)據(jù)庫持久層框架,自然要介紹下它下的使用

  • 在mapper.xml里面配置如下:
    假設(shè)a為主鍵
<insert id="insertOrUpdate">
        INSERT INTO t1 (a,b,c) 
        values
        <foreach collection="list" item="item"  separator=",">
            (#{item.a},#{item.b},#{item.c})
        </foreach>
        ON DUPLICATE KEY UPDATE c=values(c),b=values(b)
 </insert>
  • 對應(yīng)的mapper接口可以定義為:
long insertOrUpdate(List<Test> list);
class Test{
private int a;
private int b;
private int c;
...
}

注:mysql中sql字符串大小有限制,我本機的mysql上執(zhí)行show VARIABLES like '%max_allowed_packet%';結(jié)果為max_allowed_packet為4M:

image.png

四、參考

https://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容