1. 程式人生 > 其它 >MySQL之"資料庫中沒有就建立,有就修改"ON DUPLICATE KEY UPDATE

MySQL之"資料庫中沒有就建立,有就修改"ON DUPLICATE KEY UPDATE

一.場景

當你想存入一條資料到擴充套件表中(主表下附表),但這個擴充套件表並非一定會建立,就會讓其工程邏輯複雜化

(也就是說:有可能建立主表資料的同時不會建立擴充套件表資料,這樣就會照成你想修改的時候,擴充套件表本身是沒有資料的,導致你可能要先建立資料,但這樣就需要在呼叫一次建立方法,並且要做邏輯上的判斷)

而本次介紹的SQL功能就是:解決如果資料庫中該表沒有資料就建立,有資料就修改的需求

優點:

方便、優雅

缺點:

高併發的場景下,容易鎖死,所以還是不太建議使用的

msyql的innodb5.0以上版本有很多的陷阱,即有可能導致death lock死鎖也有可能導致主從模式下的replication產生資料不一致

產生death lock原理

insert ... on duplicate key 在執行時,innodb引擎會先判斷插入的行是否產生重複key錯誤,如果存在,在對該現有的行加上S(共享鎖)鎖,如果返回該行資料給mysql,然後mysql執行完duplicate後的update操作,然後對該記錄加上X(排他鎖),最後進行update寫入。

可參考文章:https://www.2cto.com/database/201711/695662.html

MySQL文章:https://bugs.mysql.com/bug.php?id=52020

注意:

①一個唯一鍵,或者主鍵(insert into列中包含該鍵)

②不能跟where條件

③表中有多個唯一鍵時可能造成死鎖,使用時注意

強調一點:

on duplicate key update後面跟全部更新的欄位=值,也就是說insert into填寫values()中的值,全部以key=value的形式填寫在update後面,否則會出現不更新,或者更新某些欄位的情況!!!

二.格式

INSERT INTO 表名(新增的欄位1, 新增的欄位2) VALUES ("欄位1的值", 欄位2的值) ON DUPLICATE KEY UPDATE 修改的欄位= VALUES(修改的欄位)

三.案例

根據SKU調整下載視訊次數

  • product_sku   SKU
  • download_video_number  下載視訊次數
# 這樣如果product_extend表中沒有資料就直接執行INSERT INTO 建立,有值就執行UPDATE修改download_video_number欄位
INSERT
INTO product_extend (product_sku, download_video_number) VALUES ("wzw", 2) ON DUPLICATE KEY UPDATE download_video_number = VALUES(download_video_number)

四.擴充套件

直接SQL執行

在查資料的時候發現了另一種新的寫法可用於參考:這裡的區別是直接用SQL查詢直接替代傳值,只需要傳入條件product_sku就可以了

INSERT INTO order_burst_sku (order_id, sku, quantity, create_time)
        (
            SELECT t2.order_id order_id, t2.product_sku sku, SUM(t2.sale_quantity) quantity, NOW()
            FROM order t1
            LEFT JOIN order_item t2 ON t1.platform_order_id = t2.order_id
            WHERE 1 = 1t2.product_sku = 'wzw'
            GROUP BY t2.order_id, t2.product_sku
        ) ON DUPLICATE KEY UPDATE quantity = VALUES(quantity)

亦可以參考以下格式