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

传送门======>

MySQL保存或更新 saveOrUpdate的更多相关文章

  1. Hibernate入门(八)级联保存或更新(含问题在末尾,求大佬指点..)

    级联保存或更新CASCADE 级联保存或更新: 作用就是:保存一方的数据的时候,会把关联的对象也同时保存. 级联保存或更新的配置: 属性名:cascade 属性值: 1.none:所有情况下均不进行关 ...

  2. SparkStreaming直连方式读取kafka数据,使用MySQL保存偏移量

    SparkStreaming直连方式读取kafka数据,使用MySQL保存偏移量 1. ScalikeJDBC 2.配置文件 3.导入依赖的jar包 4.源码测试 通过MySQL保存kafka的偏移量 ...

  3. Mysql跨表更新 多表update sql语句总结

    Mysql跨表更新一直是大家所关心的话题,本文介绍mysql多表 update在实践中几种不同的写法 假定我们有两张表,一张表为Product表存放产品信息,其中有产品价格列Price:另外一张表是P ...

  4. mysql保存中文乱码的原因和解决办法

    当你遇到这个mysql保存中文乱码问题的时候,期待找到mysql保存中文乱码的原因和解决办法这样一篇能解决问题的文章是多么激动人心.    也许30%的程序员会选择自己百度,结果发现网友已经贴了很多类 ...

  5. 基于Html5 Plus + Vue + Mui 移动App开发(三)-文件操作(读取、保存、更新数据)

      随着手机的发展,现在越来越多的人选择在手机上看书.无论是专业书籍.文学.英语还是网络小说,在手机上看新闻成了人们处理零碎时间的办法.在智能手机里安装一个资讯APP,可以随时.随地查看自己想看的资讯 ...

  6. PHP利用MySQL保存session

    实现环境: PHP 5.4.24 MySQL 5.6.19 OS X 10.9.4/Apache 2.2.26 一.代码 CREATE TABLE `session` ( `skey` ) CHARA ...

  7. Mysql跨表更新

    Mysql跨表更新一直是大家所关心的话题,本文介绍mysql多表 update在实践中几种不同的写法,需要的朋友可以参考下 假定我们有两张表,一张表为Product表存放产品信息,其中有产品价格列Pr ...

  8. PHP利用MySQL保存session(php5.4之前的处理)

    简介 使用MySQL保存session,需要保存三个关键性的数据:session id.session数据.session生命期. 考虑到session的使用方式,没必要使用InnoDB引擎,MyIS ...

  9. mysql 保存23:59:59 自动加一秒

    mysql保存系统传递的时间会诡异的增加一秒钟使用如下工具类: public static Date getEndOfDay(Date date) { Calendar calendarEnd = C ...

随机推荐

  1. Cloudstack 的搭建

    Note: 关闭了NFS Storage 的防火墙 service iptables stop 1. 新创建的Linux没有获取IP; vi /etc/sysconfig/network-script ...

  2. [转帖]你们知道LTE Cat.1到Cat.10 那Cat.0呢?

    你们知道LTE Cat.1到Cat.10 那Cat.0呢? https://network.pconline.com.cn/638/6389637_all.html#content_page_3 1大 ...

  3. 去掉DataTable列中的重复行

    DataTable  dt = ds.Tables[0];    //获得 DataTable  DataView dv = new DataView(dt);DataTable dt2 = dv.T ...

  4. 棋盘游戏 HDU - 1281 (删点 二分匹配)

    小希和Gardon在玩一个游戏:对一个N*M的棋盘,在格子里放尽量多的一些国际象棋里面的“车”,并且使得他们不能互相攻击,这当然很简单,但是Gardon限制了只有某些格子才可以放,小希还是很轻松的解决 ...

  5. MT【77】函数的定义理解

    答案:D.比如C 中令$x^2+1=2,x=-1,1,$ 得$f(2)=0,2$与定义矛盾,A,B同理排除. D中注意到$x^2-2x$与$|x-1|$对称轴都是$x=1$. 评:函数的定义,首先是两 ...

  6. 洛谷SP16580 QTREE7 - Query on a tree VII(LCT,multiset)

    洛谷题目传送门 思路分析 维护子树最值还是第一次写QwQ 因为子树的最值会变化,所以不能简单地把最值记下来,还要维护一个平衡树,把每个子树的最大值扔进去,来资磁插入.删除和查询最值. 然后我就懒得手写 ...

  7. 解题:EXNR #1 金拱门

    题面 大力统计题 考虑把和的平方拆开,最终就是许多对位置乘起来求和.所以考虑每对位置的贡献,对于$a_{i,j}$和$a_{k,h}(1<=i<=k<=n,1<=j<=h ...

  8. oracle数据库连接池查看

    select username , count(*), machine from v$session where username is not null group by username, mac ...

  9. ssm框架中Controller层的junit测试_我改

    Controller测试和一般其他层的junit测试可以共用一个BaseTest 一.BaseTest如下: @RunWith(SpringJUnit4ClassRunner.class) @WebA ...

  10. Kafka+Zookeeper+Filebeat+ELK 搭建日志收集系统

    ELK ELK目前主流的一种日志系统,过多的就不多介绍了 Filebeat收集日志,将收集的日志输出到kafka,避免网络问题丢失信息 kafka接收到日志消息后直接消费到Logstash Logst ...