批量插入数据时防重复的实用技巧

时间:2025-04-03 22:41:58

场景

业务上经常遇到批量插入数据的场景,比如上传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 语句类似,只不过该语句的功能如下

  1. 表中存在该记录,则根据update后面指定的内容进行更新相应的字段值;
  2. 表中不存在该记录,则直接插入

判断记录重复的依据依然是主键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:若根据业务字段去重,需要先建好相应的唯一索引。