MySQL保存或更新 saveOrUpdate


1. 引子

在項目開發過程中,有一些數據在寫入時候,若已經存在,則覆蓋即可。這樣可以防止多次重復寫入唯一鍵沖突報錯。下面先給出兩個MyBatis配置文件中使用saveOrUpdate的示例

<!-- 單條數據保存 --> <insert id="saveOrUpdate" parameterType="TestVo"> insert into table_name ( col1, col2, col3 ) values ( #{field1}, #{field2}, #{field3} ) on duplicate key update col1 = #{field1}, col2 = #{field2}, col3 = #{field3} </insert> <!-- 批量保存 --> <insert id="batchSaveOrUpdate" parameterType="java.util.List"> insert into table_name ( col1, col2, col3 ) <foreach collection="list" item="item" index="index" separator=","> values ( #{item.field1}, #{item.field2}, #{item.field3} ) </foreach> on duplicate key update col1 = VALUES (col1), col2 = VALUES (col2), col3 = VALUES (col3) </insert>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

其實對於單行數據on duplicate key update也可以和批量數據保存一樣使用VALUES表達式(VALUES指向新數據)。

通過上面的例子初識MySQL ON DUPLICATE KEY UPDATE語法,下面繼續學習~~

2. ON DUPLICATE KEY UPDATE 語法

MySQL的ON DUPLICATE KEY UPDATE語法是指包含ON DUPLICATE KEY UPDATE子句的INSERT語句,當新增的這條語句在數據庫中已經存在(已經存在是指這條數據包含的主鍵或者唯一鍵在數據庫已經存在),則會更新數據庫對應的老數據。

下面兩條sql語句就是等效的,其中table表中a是唯一鍵

INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1; UPDATE table SET c=c+1 WHERE a=1;
  • 1
  • 2
  • 3
  • 4

若在table表中,不僅僅存在a這個唯一鍵,b也是唯一鍵的情況下,以下兩條語句就是等效的

INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1; UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;
  • 1
  • 2
  • 3
  • 4

上面這條update語句的含義是:從表中取出滿足a=1或者b=2的一條數據,進行更新操作。

下面重點了解以下幾個問題:

2.1 多個唯一鍵

對於一張包含多個唯一鍵(多個唯一鍵指有多個鍵,而不是一個鍵中包含多個字段)的情況下,一定要注意多個唯一鍵是否會對應多條數據

從上述第二個例子可以看出,ON DUPLICATE KEY UPDATE會根據a=1或b=2匹配出一條數據進行更新,當此時對應多條數據時候,這種更新操作就會有不確定性。(從另一個角度考慮,若多個唯一鍵都是一一對應,那么更新操作也不會有問題)

2.2 影響行數返回值

數據不存在,新增數據返回1 
數據已存在,修改數據返回2 
數據已存在,但未變化返回0

數據是否存在根據唯一鍵判斷,數據是否修改根據ON DUPLICATE KEY UPDATE后的語句判斷

下面是一個ON DUPLICATE KEY UPDATE返回值各種情況的簡單實例:

mysql> CREATE TABLE test1 (a INT PRIMARY KEY AUTO_INCREMENT , b INT, c INT); Query OK, 0 rows affected (0.01 sec) mysql> INSERT INTO test1(a, b ,c) VALUES (1, 1, 1); Query OK, 1 row affected (0.00 sec) mysql> select * from test1; +---+------+------+ | a | b | c | +---+------+------+ | 1 | 1 | 1 | +---+------+------+ 1 row in set (0.00 sec) mysql> INSERT INTO test1(a, b ,c) VALUES (1, 1, 1) ON DUPLICATE KEY UPDATE c = c + 1; Query OK, 2 rows affected (0.00 sec) mysql> select * from test1; +---+------+------+ | a | b | c | +---+------+------+ | 1 | 1 | 2 | +---+------+------+ 1 row in set (0.00 sec) mysql> INSERT INTO test1(a, b ,c) VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE c = c + 1; Query OK, 1 row affected (0.00 sec) mysql> select * from test1; +---+------+------+ | a | b | c | +---+------+------+ | 1 | 1 | 2 | | 2 | 2 | 2 | +---+------+------+ 2 rows in set (0.00 sec) mysql> INSERT INTO test1(a, b ,c) VALUES (2, 2, 3) ON DUPLICATE KEY UPDATE c = VALUES(c); Query OK, 2 rows affected (0.00 sec) mysql> select * from test1; +---+------+------+ | a | b | c | +---+------+------+ | 1 | 1 | 2 | | 2 | 2 | 3 | +---+------+------+ 2 rows in set (0.00 sec) mysql> INSERT INTO test1(a, b ,c) VALUES (2, 2, 3) ON DUPLICATE KEY UPDATE c = VALUES(c); Query OK, 0 rows affected (0.00 sec) mysql> select * from test1; +---+------+------+ | a | b | c | +---+------+------+ | 1 | 1 | 2 | | 2 | 2 | 3 | +---+------+------+ 2 rows in set (0.00 sec)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

注意返回值與新增、修改之間的關系

2.3 新老數據引用

從上面的例子,和觸發器做類比,在ON DUPLICATE KEY UPDATE子句后面,直接使用字段名,引用的是老數據;使用VALUES,引用的是要插入更新的新數據。(例如: c=c+1是在老數據的c字段上加1,c=VALUES(c)是拿新數據覆蓋老數據)

2.4 批量保存

批量保存使用ON DUPLICATE KEY UPDATE的場景,請回過頭參照文章開始的示例中的第二個用法。

參考自官網:http://dev.mysql.com/doc/refman/5.5/en/insert-on-duplicate.html

傳送門======>

 


免責聲明!

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



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