mysql 插入重復值 INSERT ... ON DUPLICATE KEY UPDATE


 

       向數據庫插入記錄時,有時會有這種需求,當符合某種條件的數據存在時,去修改它,不存在時,則新增,也就是saveOrUpdate操作。這種控制可以放在業務層,也可以放在數據庫層,大多數數據庫都支持這種需求,如Oracle的merge語句,再如本文所講的MySQL中的INSERT ... ON DUPLICATE KEY UPDATE語句。

       該語句是基於唯一索引或主鍵使用,比如一個字段a被加上了unique index,並且表中已經存在了一條記錄值為1,下面兩個語句會有相同的效果:

[sql]  view plain  copy
 
 print?在CODE上查看代碼片派生到我的代碼片
  1. INSERT INTO table (a,b,c) VALUES (1,2,3)  
  2.   ON DUPLICATE KEY UPDATE c=c+1;  
  3.   
  4. UPDATE table SET c=c+1 WHERE a=1;  

       ON DUPLICATE KEY UPDATE后面可以放多個字段,用英文逗號分割。使用ON DUPLICATE KEY UPDATE,最終如果插入了一個新行,則受影響的行數是1,如果修改了已存在的一行數據,則受影響的行數是2。

       如果字段b也被加上了unique index,則該語句和下面的update語句是等效的:

[sql]  view plain  copy
 
 print?在CODE上查看代碼片派生到我的代碼片
  1. UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;  

       如果a=1 OR b=2匹配了多行,則只有一行會被修改。通常的,在ON DUPLICATE KEY UPDATE語句中,我們應該避免多個唯一索引的情況。如果需要插入或更新多條數據,並且更新的字段需要根據其它字段來運算時,可以使用如下語句:

[sql]  view plain  copy
 
 print?在CODE上查看代碼片派生到我的代碼片
  1. INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)  
  2.   ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);  

       在ON DUPLICATE KEY UPDATE后面使用VALUES()方法,這個語句等同於下面的兩個語句:

[sql]  view plain  copy
 
 print?在CODE上查看代碼片派生到我的代碼片
  1. INSERT INTO table (a,b,c) VALUES (1,2,3)  
  2.   ON DUPLICATE KEY UPDATE c=3;--1+2  
  3. INSERT INTO table (a,b,c) VALUES (4,5,6)  
  4.   ON DUPLICATE KEY UPDATE c=9;--4+5  

       如果一個表中包含了一個auto_increment的字段,每次insert數據后,可以通過last_insert_id()方法返回最后自動生成的值,如果通過INSERT ... ON DUPLICATE KEY UPDATE語句修改了一條數據,那么再通過last_insert_id()方法獲取的值將不正確,實際測試中是多了一個數,比如向表中增加了3條數據,那么通過last_insert_id()方法得到的值是3,但是通過該語句修改了一條數據后,通過last_insert_id()方法得到的值是4。如果想解決該問題,可以通過如下語句:

[sql]  view plain  copy
 
 print?在CODE上查看代碼片派生到我的代碼片
  1. INSERT INTO table (a,b,c) VALUES (1,2,3)  
  2.   ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;  

 

       重點是這句id=LAST_INSERT_ID(id)。

       英文原文:https://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html

    

方案一:使用ignore關鍵字

如果是用主鍵primary或者唯一索引unique區分了記錄的唯一性,避免重復插入記錄可以使用:

 

復制代碼代碼如下:

 INSERT IGNORE INTO `table_name` (`email`, `phone`, `user_id`) VALUES ('test9@163.com', '99999', '9999'); 
 


這樣當有重復記錄就會忽略,執行后返回數字0

 

還有個應用就是復制表,避免重復記錄:

復制代碼代碼如下:

 INSERT IGNORE INTO `table_1` (`name`) SELECT `name` FROM `table_2`; 
 
、復制舊表的數據到新表(假設兩個表結構不一樣) 
IN SERT INTO 新表(字段1,字段2,.......) SELECT 字段1,字段2,...... FROM 舊表 

mysql中primary key重復時的處理辦法

當insert進數據表, 發生唯一key(unique key與primary key)重復時, 會發生duplicate key錯誤.

 這種情況有三種處理方法, 以下面的數據結構為例子

 

mysql> use test;

mysql> create table `user` (`userid` int(11) DEFAULT NULL, `username` varchar(255) NOT NULL DEFAULT '');

給加上userid列primary key 

mysql> alter table `user` add primary key `userid` (`userid`);

 

插入數據

mysql> insert into `user` values (1, 'eric'), (2, 'jesus'); 

 

現在我要插入或者編輯userid為1的記錄, 但我不知道里面是否已經存在該記錄.

 

1, 先刪除再插入之

mysql> delete from user where userid = 1;

mysql> insert into user values (1, 'xxxxx') ;

 

2, 使用replace into

mysql> replace into user values (1, 'newvalue'); 

這種情況下邏輯是這樣的, mysql先判斷記錄是否存在, 若存在則先刪除之, 再自行insert. 所以你能看到這條語句執行后affected rows是2條(當然前提是你的數據表里userid為1的數據只有1條) 

 

3, 使用insert into ... on duplicate key  update

 mysql> insert into user1 values (1, 'newvalueagain') on duplicate key update user1.username = VALUES(username);

這條語句的affected rows也是2.

 

當然還有另外的處理方式就是直接用php來實現,

先select出來, 發現沒結果則insert, 否則update.

還可以先update, 發現affected rows是0, 則insert.

 

但明顯這倆種辦法都沒有把工作直接交給mysql處理效率高 。

 

 參考:

http://blog.csdn.net/ghsau/article/details/23557915

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM