INSERT ... ON DUPLICATE KEY UPDATE

網上關於INSERT … ON DUPLICATE KEY UPDATE大多數文章都是同一篇文章轉來轉去,首先這個語法的目的是爲了解決重複性,當數據庫中存在某個記錄時,執行這條語句會更新它,而不存在這條記錄時,會插入它。

相當於 先判斷一條記錄是否存在,存在則update,否則insert。其語法是:

INSERT INTO tablename(field1,field2, field3, ...) VALUES(value1, value2, value3, ...) ON DUPLICATE KEY UPDATE field1=value1,field2=value2, field3=value3, ...;
tablename是表名,field1,field2,field3等是字段名稱,value1,value2,value3等是字段值。

例如:

INSERT INTO t_stock_chg(f_market, f_stockID, f_name) VALUES('SH', '600000', '白雲機場') ON DUPLICATE KEY UPDATE f_market='SH', f_name='浦發銀行';

這條語句如果記錄不存在,插入該記錄;存在將f_market改爲SH,f_name改爲浦發銀行。現在有個問題是:這條語句判斷該條記錄是否存在的標準是什麼?由於同一個值是可以同時出現在多個記錄中的,所以必須有個字段是唯一不能重複的。

規則是這樣的:如果你插入的記錄導致一個UNIQUE索引或者primary key(主鍵)出現重複,那麼就會認爲該條記錄存在,則執行update語句而不是insert語句,反之,則執行insert語句而不是更新語句。所以 ON DUPLICATE KEY UPDATE是不能寫where條件的,例如如下語法是錯誤的:

INSERT INTO t_stock_chg(f_market, f_stockID, f_name) VALUES('SH', '600000', '白雲機場') ON DUPLICATE KEY UPDATE f_market='SH', f_name='浦發銀行' WHERE f_stockID='600000';

因爲由UNIQUE索引或者主鍵保證唯一性,不需要WHERE子條件。所以上面的INSERT INTO t_stock_chg(f_market, f_stockID, f_name) VALUES(‘SH’, ‘600000’, ‘白雲機場’) ON DUPLICATE KEY UPDATE f_market=‘SH’, f_name=‘浦發銀行’;中f_stockID就是唯一主鍵。

這裏特別需要注意的是:如果行作爲新記錄被插入,則受影響行的值爲1;如果原有的記錄被更新,則受影響行的值爲2,如果更新的數據和已有的數據一模一樣,則受影響的行數是0,這意味着不會去更新,也就是說即使你有的時間戳是自動記錄最後一次的更新時間,這個時間戳也不會變動。例如:

CREATE TABLE `t_stock_chg` (
`f_market` varchar(64) NOT NULL COMMENT '市場',
`f_stockID` varchar(10) NOT NULL DEFAULT '' COMMENT '股票代碼',
`f_updatetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '插入時間戳',
`f_name` varchar(16) DEFAULT NULL COMMENT '股票名稱',
PRIMARY KEY (`f_market`,`f_stockID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

這裏的字段f_updatetime每次在更新數據時會自動更新,但是如果記錄中存在某條數據,後來又更新它,而更新的數據和原數據一模一樣,那麼這個字段也不會更新,仍然是上一次的時間。此時INSERT … ON DUPLICATE KEY UPDATE影響行數是0。

在對一對多屬性修改時我們可能會常常用到該功能,不用 專門業務代碼去判斷是新增還是修改;

-- 一個活動可能對應多個商品的多個SKU,可能一個商品有多個SKU但是隻要其中幾個SKU參加活動
create table jiuyoulife_uat.j_shop_activity_goods
(
   group_id             national int(11) not null comment '團購活動ID',
   product_id           national char(32) not null comment '產品ID',
   goods_id             national char(32) not null comment 'goods_id',
   activity_type        int(2) not null default NULL comment '活動類型:0團購',
   stock                int(11) comment '庫存',
   super_price          double comment '活動價格',
   sales                int(11) comment '銷售數量',
   settle_type          int(2) default 0 comment '結算方式:0按比例結算1按底價結算',
   ratio                double comment '底價:浮點數;結算比例(1-100)%',
   create_time          datetime default CURRENT_TIMESTAMP,
   update_time          datetime,
   primary key (group_id, goods_id)
);


-- 插入更新:如果三個主鍵相同則更新,否則進行插入操作
insert into j_shop_activity_goods ( group_id, product_id, goods_id, activity_type, stock, super_price, sales, settle_type, ratio, create_time, update_time) values 
( 1, 1, 1, 0, 100,0.01, 0, 0, 10,NOW(),NOW() ) , 
( 1, 1, 1, 0, 100,0.01, 0, 0, 10,NOW(),NOW() ) 
 ON DUPLICATE KEY UPDATE 
 activity_type = VALUES(activity_type), 
 stock = VALUES(stock), 
 super_price = VALUES(super_price), 
 settle_type = VALUES(settle_type),
  ratio = VALUES(ratio), 
  update_time = VALUES(update_time) 

參考文

前半部分原文出自:
沫小淘https://www.cnblogs.com/moxiaotao/p/9431808.html

發佈了158 篇原創文章 · 獲贊 72 · 訪問量 33萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章