MySQL保存或更新 saveOrUpdate

在項目開發過程當中,有一些數據在寫入時候,若已經存在,則覆蓋便可。這樣能夠防止屢次重複寫入惟一鍵衝突報錯。下面先給出兩個MyBatis配置文件中使用saveOrUpdate的示例html

<!-- 單條數據保存 -->
<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>

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

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

2. ON DUPLICATE KEY UPDATE 語法

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

下面兩條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的一條數據,進行更新操做。spa

下面重點了解如下幾個問題:code

2.1 多個惟一鍵

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

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

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)

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

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

相關文章
相關標籤/搜索