mysql replace into 的使用情況


replace into的存在的幾種情況

  • 當表存在主鍵並且存在唯一鍵的時候
    • 如果只是主鍵沖突
復制代碼
mysql> select * from auto; +----+---+------+---------+ | id | k | v | extra | +----+---+------+---------+ | 2 | 2 | 2 | extra 2 | | 3 | 3 | 3 | extra 3 | | 4 | 1 | 1-1 | NULL | +----+---+------+---------+ 3 rows in set (0.00 sec) mysql> mysql> show create table auto\G *************************** 1. row *************************** Table: auto Create Table: CREATE TABLE `auto` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `k` int(10) unsigned NOT NULL, `v` varchar(100) DEFAULT NULL, `extra` varchar(200) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_k` (`k`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 1 row in set (0.00 sec)
復制代碼

這里我們插入一條主鍵已經存在的4的數據

復制代碼
mysql> replace into auto(id,k)values(4,5); Query OK, 2 rows affected (0.01 sec) mysql> select * from auto; +----+---+------+---------+ | id | k | v | extra | +----+---+------+---------+ | 2 | 2 | 2 | extra 2 | | 3 | 3 | 3 | extra 3 | | 4 | 5 | NULL | NULL | +----+---+------+---------+ 3 rows in set (0.00 sec) mysql> show create table auto \G *************************** 1. row *************************** Table: auto Create Table: CREATE TABLE `auto` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `k` int(10) unsigned NOT NULL, `v` varchar(100) DEFAULT NULL, `extra` varchar(200) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_k` (`k`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 1 row in set (0.00 sec)
復制代碼

 發現,auto_increment並沒有+1,而是針對原來的那一條id=4的記錄進行了update,因為沒有指定其他列(v,extra)的值,所以,update的時候都使用了默認值.

  • 如果主鍵跟唯一鍵都沖突並且在同一行里
復制代碼
mysql> select * from auto; +----+---+------+---------+ | id | k | v | extra | +----+---+------+---------+ | 2 | 2 | 2 | extra 2 | | 3 | 3 | 3 | extra 3 | | 4 | 5 | NULL | NULL | | 5 | 6 | 6 | NULL | +----+---+------+---------+ 4 rows in set (0.00 sec) mysql> show create table auto \G *************************** 1. row *************************** Table: auto Create Table: CREATE TABLE `auto` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `k` int(10) unsigned NOT NULL, `v` varchar(100) DEFAULT NULL, `extra` varchar(200) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_k` (`k`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 1 row in set (0.00 sec) mysql> mysql> mysql> replace into auto(id,k,extra)values(5,6,77); Query OK, 2 rows affected (0.01 sec) mysql> select * from auto; +----+---+------+---------+ | id | k | v | extra | +----+---+------+---------+ | 2 | 2 | 2 | extra 2 | | 3 | 3 | 3 | extra 3 | | 4 | 5 | NULL | NULL | | 5 | 6 | NULL | 77 | +----+---+------+---------+ 4 rows in set (0.00 sec) mysql> show create table auto \G *************************** 1. row *************************** Table: auto Create Table: CREATE TABLE `auto` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `k` int(10) unsigned NOT NULL, `v` varchar(100) DEFAULT NULL, `extra` varchar(200) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_k` (`k`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 1 row in set (0.00 sec)
復制代碼

我們發現,auto_increment也並沒有+1,而是針對原來的那一條id=6的記錄進行了update,因為沒有指定其他列(v)的值,所以,update的時候都v使用了默認值變成了null

  • 如果主鍵跟唯一鍵都沖突不在同一行,對應2條記錄呢

我們來看下:

復制代碼
mysql> show create table auto \G
*************************** 1. row *************************** Table: auto Create Table: CREATE TABLE `auto` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `k` int(10) unsigned NOT NULL, `v` varchar(100) DEFAULT NULL, `extra` varchar(200) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_k` (`k`) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1 1 row in set (0.00 sec) mysql> select * from auto; +----+---+------+---------+ | id | k | v | extra | +----+---+------+---------+ | 2 | 2 | 2 | extra 2 | | 3 | 3 | 3 | extra 3 | | 4 | 5 | NULL | NULL | | 6 | 6 | 66 | NULL | +----+---+------+---------+ 4 rows in set (0.00 sec) mysql> replace into auto(id,k,v)values(6,2,88); Query OK, 3 rows affected (0.03 sec)
復制代碼

像上面的,主鍵id=6對應一條記錄,唯一索引k=2對應id=2的另外一條記錄,所以我們當前插入的記錄就會跟2行數據有沖突,我們replace into 看看會有什么結果

復制代碼
mysql> replace into auto(id,k,v)values(6,2,88); Query OK, 3 rows affected (0.03 sec) mysql> select * from auto; +----+---+------+---------+ | id | k | v | extra | +----+---+------+---------+ | 3 | 3 | 3 | extra 3 | | 4 | 5 | NULL | NULL | | 6 | 2 | 88 | NULL | +----+---+------+---------+ 3 rows in set (0.00 sec) mysql> show create table auto \G *************************** 1. row *************************** Table: auto Create Table: CREATE TABLE `auto` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `k` int(10) unsigned NOT NULL, `v` varchar(100) DEFAULT NULL, `extra` varchar(200) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_k` (`k`) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1 1 row in set (0.00 sec)
復制代碼

我們發現auto_increment並沒有+1,MySQL把原來的id=6的這條記錄上進行uppdate,但是發現唯一索引k出現了沖突,所以就把對應沖突的那條數據刪除,再進行更新,由於沒有指定更新字段extra的數據,所以就把extra更新為默認數據

  • 如果僅僅是唯一鍵沖突呢?
復制代碼
mysql> select * from auto; +----+---+------+---------+ | id | k | v | extra | +----+---+------+---------+ | 2 | 2 | 2 | extra 2 | | 3 | 3 | 3 | extra 3 | | 4 | 5 | NULL | NULL | | 5 | 6 | NULL | 77 | +----+---+------+---------+ 4 rows in set (0.00 sec) mysql> show create table auto \G *************************** 1. row *************************** Table: auto Create Table: CREATE TABLE `auto` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `k` int(10) unsigned NOT NULL, `v` varchar(100) DEFAULT NULL, `extra` varchar(200) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_k` (`k`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 1 row in set (0.00 sec) mysql> mysql> replace into auto(k,v)values(6,66); Query OK, 2 rows affected (0.04 sec) mysql> select * from auto; +----+---+------+---------+ | id | k | v | extra | +----+---+------+---------+ | 2 | 2 | 2 | extra 2 | | 3 | 3 | 3 | extra 3 | | 4 | 5 | NULL | NULL | | 6 | 6 | 66 | NULL | +----+---+------+---------+ 4 rows in set (0.00 sec) mysql> show create table auto \G *************************** 1. row *************************** Table: auto Create Table: CREATE TABLE `auto` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `k` int(10) unsigned NOT NULL, `v` varchar(100) DEFAULT NULL, `extra` varchar(200) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_k` (`k`) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1 1 row in set (0.00 sec)
復制代碼

這時候,我們發現,,auto_increment已經+1了。MySQL這時候的執行步驟是,首先往表里面插入一條數據,這時候auto_increment+1,但是在插入的時候發現唯一索引的k沖突了,然后把沖突的這條數據刪除,然后重新插入,對於沒有指定其他列(extra)的值,如extra都使用了默認值變成了null

現在我們可以下結論了:

  1. 當replace into 記錄只與主鍵沖突的時候,auto_increment不會增加,它會對與主鍵沖突的那一條記錄進行更新,沒有指定的列將會被更新為默認值
  2. 當replace into 記錄與主鍵跟唯一索引同時沖突的時候,auto_increment不會增加
    1. 如果沖突的主鍵和索引在同一行記錄,則replace into只做更新,對於沒有指定值的其他列,將會被更新為默認值,
    2. 如果沖突的主鍵和索引分別對應2行數據,則MySQL將會刪除唯一索引的那一行記錄,更新對應主鍵的那一行記錄。
  3. 當replace into 記錄只與唯一索引進行沖突的時候,auto_increment + 1,再對數據進行更新。
  • 最后我們可以對總結分析下,MySQL對replace into的操作是首先是insert操作,如果insert失敗,則對insert失敗的這條記錄進行update,如果update還是失敗,則會進行delete操作之后再update。
  • 具體流程是這樣的:insert記錄,發現主鍵沖突,則update這一行,update的時候發現存在唯一鍵沖突,則delete對應的唯一鍵的行后再進行update。如果insert成功,auto_increment自然+1了,然后對這條記錄進行update,update的時候發現存在唯一鍵沖突,則delete對應的唯一鍵的行后再進行update。


免責聲明!

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



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