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. C语言入门:06.基本运算

    一.算术运算 C语言一共有34种运算符,包括了常见的加减乘除运算 1. 加法运算+ 除了能做加法运算,还能表示正号:+5.+90 2.减法运算- 除了能做减法运算,还能表示符号:-10.-29 3. ...

  2. 一本通1646GT 考试

    1646:GT 考试 时间限制: 1000 ms         内存限制: 524288 KB [题目描述] 阿申准备报名参加 GT 考试,准考证号为 n 位数 X1X2⋯Xn(0≤Xi≤9),他不 ...

  3. BZOJ2648 SJY摆棋子(KD-Tree)

    板子题. #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> # ...

  4. gdb调试coredump文件

    linux上程序崩溃起来挺烦人,不过linux 比较好的是有gdb. 1.生成coredump文件 echo "ulimit -c unlimited" >> /etc ...

  5. 2017年11月GitHub上最热门的Java项目出炉

    2017年11月GitHub上最热门的Java项目出炉~ 一起来看看这些项目你使用过哪些呢? 1分布式 RPC 服务框架 dubbohttps://github.com/alibaba/dubbo S ...

  6. How to 对拍?

    对拍从数学的统计学角度来说是一个好的方法,至少能在你竞赛中帮你拿回一些分--yzr大牛pas的对拍一开始还没写过,突然想学一下对拍.那么就学吧.dp水题(搜索):https://www.luogu.o ...

  7. (转)win下修改jdk环境变量后,java版本不变 java -version

    背景:在windows下安装了多个版本的jdk,发现修改环境变量无法切换. win 7环境下修改JAVA_HOME后,在命令行执行:java -version 发现版本没有变化,以为需要重启才行,就把 ...

  8. Spring MVC测试框架

    原文链接:http://jinnianshilongnian.iteye.com/blog/2004660 Spring MVC测试框架详解——服务端测试 博客分类: springmvc杂谈 spri ...

  9. spring注入时报错::No qualifying bean of type 'xxx.xxMapper'

    做一个小项目,因为有 baseService,所以偷懒就没有写单独的每个xxService接口,直接写的xxServiceImpl,结果在service实现类中注入Mapper的时候,用的 @Auto ...

  10. javaWeb接口开发

    链接:http://blog.csdn.net/zxw136511485/article/details/51437115