MySQL保存或更新 saveOrUpdate

在项目开发过程中,有一些数据在写入时候,若已经存在,则覆盖即可。这样可以防止多次重复写入唯一键冲突报错。下面先给出两个MyBatis配置文件中使用saveOrUpdate的示例

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

其实对于单行数据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是唯一键

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

若在table表中,不仅仅存在a这个唯一键,b也是唯一键的情况下,以下两条语句就是等效的

1INSERT INTO table (a,b,c) VALUES (1,2,3) 2 ON DUPLICATE KEY UPDATE c=c+1; 3 4UPDATE 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返回值各种情况的简单实例:

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

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

KVM调整cpu和内存

一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid