MySQL:插入更新語句 ON DUPLICATE KEY UPDATE

建立一張表node_status:

+--------------+--------------+------+-----+---------+-------+
| Field        | Type         | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| node_name    | varchar(100) | NO   | PRI | NULL    |       |
| ip           | varchar(100) | NO   |     | NULL    |       |
| site         | varchar(100) | NO   |     | NULL    |       |
| frp_num      | int(11)      | NO   |     | NULL    |       |
| home_free    | bigint(20)   | NO   |     | NULL    |       |
| mem_use      | varchar(100) | NO   |     | NULL    |       |
| last_time    | datetime     | NO   |     | NULL    |       |
| modify_time  | datetime     | NO   |     | NULL    |       |
+--------------+--------------+------+-----+---------+-------+

該表中,將node_name即節點主機名稱設爲PRIMARY KEY。

一開始只是想到了用 if else 語句,判斷主鍵是否存在,存在則更新,不存在則插入。

if not exists (select node_name from node_status where node_name = target_name)
      insert into node_status(node_name,ip,...) values('target_name','ip',...)
else
      update node_status set ip = 'ip',site = 'site',... where node_name = target_name

但是這麼寫出來,出現了兩個問題:
1、效率太差,每次都需要執行兩條SQL語句,一條語句用來判斷node_name是否在表中已經存在,另一條語句用來插入或更新表中數據。
2、高併發的情況下數據會出問題,不能保證原子性。

那麼有沒有更優雅高效的方法呢,通過查閱資料,發現MySQL一條語句很好的解決了這個問題:ON DUPLICATE KEY UPDATE
該語句的語法如下:

INSERT INTO tablename(field1,field2, field3, ...) VALUES(value1, value2, value3, ...) ONDUPLICATE KEY UPDATE field1=value1,field2=value2, field3=value3, ...;

這個語法的目的是爲了解決重複性,當數據庫中存在某個記錄時,執行這條語句會更新它,而不存在這條記錄時,會插入它。
該語句規則如下:如果你插入的記錄導致一個UNIQUE索引或者primary key(主鍵)出現重複,那麼就會認爲該條記錄存在,則執行update語句而不是insert語句,反之,則執行insert語句而不是更新語句。得到了這個插入語句的”八倍鏡“,我們可以將原來那個很LOW的方式替換掉了:

sql = """ INSERT INTO node_status(node_name,ip,site,frp_num, \
+                        home_free,mem_use,last_time,modify_time) \
+                        VALUES('%s','%s','%s','%d','%d','%s','%s','%s') \
+                        ON DUPLICATE KEY UPDATE  \
+                        ip='%s', site='%s',frp_num='%d',home_free='%d', \
+                        mem_use='%s',last_time='%s',modify_time='%s' """ % \
+                (id_value['host'], ip, site, frp_num, home_size, mem_use, last_time, modify_time),
+                 (ip, site, frp_num, home_size, mem_use, last_time, modify_time)

源:https://segmentfault.com/a/1190000014306692 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章