批量插入的去重解决方案

背景

最近项目上需要做一个Excel批量导入一批企业数据到mysql数据库,并对企业名称和企业注册号这两个特定字段去重的需求。

正文

  1. 首先我会想到的是直接用java去重;先对当前批次的数据进行内部去重,然后和数据库数据进行对比去重,最后批量插入。
1
2
3
4
5
6
7
8
9
//批量插入的SQL
<insert id="batchInsert">
insert into test_ent(ent_name,creditcode,remark)
values
<foreach collection="entList" index="index" item="item"
separator=",">
(#{item.entName},#{item.creditcode},#{item.remark})
</foreach>
</insert>

那么这里和数据库对比的时候会造成频繁的进行交互,我们都知道,这是不好的。

  1. 又想不那频繁的与数据库进行交互,又能去重,还能批量插入,是否可以直接用一条SQL实现呢?熟悉mysql的人应该知道insert ignore,它是对主键或者唯一索引的字段存在相同数据,则忽略该条数据,否则插入。正好他是复合我们的去重要求的,我们只需对企业名称和企业注册号加上唯一索引就行了。最后再改装成批量的SQL就完美了。
1
2
3
4
5
6
7
8
9
//其实就只需在上面sql的insert前面加上ignore关键字就行了。
<insert id="batchInsert">
insert ignore into test_ent(ent_name,creditcode,remark)
values
<foreach collection="entList" index="index" item="item"
separator=",">
(#{item.entName},#{item.creditcode},#{item.remark})
</foreach>
</insert>
  1. 如果我想对该表的多个字段进行去重呢?我们知道一个表加过多的索引是不好的一种行为,完全会印象数据的更新和插入,既然要批量插入,说明该表是会被频繁更新的。于是就有了INSERT INTO test_ent(ent_name,creditcode,remark) SELECT '企业1','社会信用代码1','备注1' FROM dual WHERE NOT EXISTS(SELECT ent_name,creditcode,remark FROM table WHERE ent_name='企业1' and creditcode='社会信用代码1' and remark='备注1');。那么如何把它改成批量呢?我现在唯一能想到的办法就是把多个插入sql放在同一个事物里面。

    1
    2
    3
    4
    5
    6
    <insert id="batchInsert">
    <foreach collection="entList" index="index" item="item"
    separator=";">
    INSERT INTO test_ent(ent_name,creditcode,remark) SELECT #{item.entName},#{item.creditcode},#{item.remark} FROM dual WHERE NOT EXISTS(SELECT ent_name,creditcode,remark FROM table WHERE ent_name=#{item.entName} and creditcode=#{item.creditcode} and remark=#{item.remark})
    </foreach>
    </insert>
  2. 如果有更好的批量去重方式,欢迎提供。