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)