场景
业务上经常遇到批量插入数据的场景,比如上传Excel、或者做数据同步(一次保存几十上百条记录)。保存的时候需要保证幂等性,比如订单号相同的数据不能存在多条。
- 简单的处理方式就是加上一个每次save前先查询下,存在则插入,否则更新或不处理该条数据。
- 增加某个字段的唯一索引,插入时记录中如果重复则会显式抛出MySQL的异常,需要自行处理异常。
这两种方案弊端都很明显,就是数据量小时可以接受,数据量大时速度巨慢,而且数据库的交互次数很多,占用数据库连接。
解决方案
1.使用insert ignore into 语句
SQL示例insert ignore into table (field1, field2, ...) values (property1, property2, ...), (property1, property2, ...);
与普通insert语句没有区别,只是会忽略存在的记录,根据主键或唯一键判断。
tips:若根据业务字段去重,需要先建好相应的唯一索引。
2 .使用insert into … on duplicate key update 语句
示例insert into table (field1, field2, ...) values (property1, property2, ...), (property1, property2, ...) on duplicate key update field1=values(field1), field2=values(field2), ...;
与上面insert ignore into 语句类似,只不过该语句的功能如下
- 表中存在该记录,则根据update后面指定的内容进行更新相应的字段值;
- 表中不存在该记录,则直接插入
判断记录重复的依据依然是主键primary key或唯一键 unique key。特别注意的点是 如果主键是自增的,使用该语句插入时,无论是否新增记录都是使自增起始值+1.
使用Mybatis时,XML动态mapper如下:
<insert id="batchSaveOrUpdate" parameterType="list">
insert into user (name, sex, email)
values
<foreach collection="list" item="item" index="index" separator=",">
(
#{},
#{},
#{}
)
</foreach>
ON duplicate KEY UPDATE email=values(email)
</insert>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
tips:若根据业务字段去重,需要先建好相应的唯一索引。