当前位置: 首页 > news >正文

MySQL新增插入,重复更新操作业务实现

新增插入,重复则更新或不插入操作

    • 1. 业务代码控制(先查后插)
    • 2. SQL 层面控制
      • 使用`EXISTS`判断
      • 使用索引

在写业务的时候,时常会遇到这样的情况,需要对数据进行处理,若是新的数据就直接新增到数据库中,若是数据库中已经存在的数据就不进行处理或者进行更新操作。

我在实现的过程中想到了几种方式,记录下来。

1. 业务代码控制(先查后插)

在 Java 代码中循环遍历数据,先查询是否存在,再决定是否插入(并发场景需加锁,否则可能仍有重复):

/*** 批量插入:先查后插,避免重复* @param billList 待插入数据列表*/
public void batchInsertWithCheck(List<BillDTO> billList) {for (BillDTO item : billList) {// 1. 查询是否存在重复记录int count = projectSubjectAmountMapper.countByUniqueKeys(item.getSubProjectId(), item.getRateCode(), item.getSubjectCode());// 2. 不存在则插入if (count == 0) {projectSubjectAmountMapper.insertSingle(item);}}
}

若是执行更新操作的话,则对查询到的重复记录执行更新操作即可。

缺点

  • 性能差:每条数据都需执行一次查询,数据量大时数据库交互频繁;
  • 并发风险:多线程场景下,“查询 - 插入” 的时间差可能导致重复插入(需额外加分布式锁或使用事务)。

2. SQL 层面控制

使用EXISTS判断

<insert id="batchInsertIfNotExist">INSERT INTO bus_project_subject_amount(project_id,tax_code,subject_code,amount)-- 用UNION ALL拼接多条待插入数据,每条数据先判断是否存在<foreach collection="billList" item="item" separator="UNION ALL">SELECT #{item.subProjectId}, #{item.rateCode}, #{item.subjectCode}, #{item.amount}FROM DUAL  -- DUAL是MySQL虚拟表,无实际数据,仅用于构造查询WHERE NOT EXISTS (-- 子查询:判断当前记录是否已存在SELECT 1 FROM bus_project_subject_amountWHERE project_id = #{item.subProjectId}AND tax_code = #{item.rateCode}AND subject_code = #{item.subjectCode})</foreach>
</insert>

使用索引

情况1:若是想要对已经存在的数据进行更新操作,批量插入数据,若某条记录已存在(唯一键重复),则将新数据的amount累加到原有记录的amount中(如:原有金额 100,新数据金额 50,更新后为 150)。

<insert id="batchInsertOrUpdateAmount">INSERT INTO bus_project_subject_amount(project_id,tax_code,subject_code,amount) VALUES<foreach collection="billList" item="item" separator=",">(#{item.subProjectId}, #{item.rateCode}, #{item.subjectCode}, #{item.amount})</foreach>-- 唯一键冲突时,执行金额累加更新ON DUPLICATE KEY UPDATEamount = amount + VALUES(amount)
</insert>
  • 需要在数据库中建立联合唯一索引,在唯一索引冲突的情况下,就会执行我想要的更新操作。
  • ON DUPLICATE KEY UPDATE:MySQL 特有语法,当插入触发唯一键冲突时,不报错而是执行后续更新逻辑;
  • VALUES(amount):指代本次插入语句中amount字段的新值,amount = amount + VALUES(amount) 即 “原金额 + 新金额”。
  • 在本次实践中由于我业务的特殊情况,会有重复数据的情况,因此我添加了一列计算列作为唯一索引。(计算列即我使用的几个字段的连接)

情况2:若是对已经存在的数据不进行处理,批量插入数据,若某条记录已存在(唯一键重复),则忽略该条数据的插入操作(不报错、不更新,直接跳过),仅插入无冲突的新数据。

<insert id="batchInsertIgnoreDuplicate">-- 关键:用INSERT IGNORE替代普通INSERTINSERT IGNORE INTO bus_project_subject_amount(project_id,tax_code,subject_code,amount) VALUES<foreach collection="billList" item="item" separator=",">(#{item.subProjectId}, #{item.rateCode}, #{item.subjectCode}, #{item.amount})</foreach>
</insert>
  • ON DUPLICATE KEY UPDATE:MySQL 特有语法,当插入触发唯一键冲突时,不报错而是执行后续更新逻辑;
  • VALUES(amount):指代本次插入语句中amount字段的新值,amount = amount + VALUES(amount) 即 “原金额 + 新金额”。

The End.

http://www.dtcms.com/a/483853.html

相关文章:

  • linux重启网络(systemctl restart network)会不会导致连接断开?
  • 怎么用云服务器建设网站wordpress 商务主题
  • Monitoring: 1靶场渗透
  • 网店网站建设哪家小吃培训机构排名前十
  • 科技类网站源码百度h5游戏中心
  • 对伯努利过程的理解
  • 临沂网站建设步骤广州网站建设推广公司有哪些
  • 法律网站的建设流程提交网址
  • 广州市住房和城乡建设厅网站首页怎么注册微网站吗
  • 10年网站设计祥汇云江西建设厅网站查询施工员
  • dedecms网站关键词网址之家哪个好
  • Linux1014 shell:sed c s/ ,#!/bin/sed -f ./sed.sh 1.txt ,1.sed 1.txt, ,
  • HyperWorks许可证与其他软件的卓越集成
  • 辽源建站公司免费聊天软件
  • 如何让便笺实现开机自启动
  • 工业网站模板wordpress 不在根目录
  • 湖北智能网站建设找哪家图床外链生成器
  • 做销售如何在网站上搜集资料织梦网站后台模版更换
  • 做网站最快的编程语言注册wordpress账号
  • MobiOffice解锁高级功能版 v15.9.57971 安卓手机doc, docx ppt, .pptx pdf办公软件
  • 机关网站建设的作用三亚网站建设哪家专业
  • java数据结构--时间和空间复杂度
  • 运城市建设局网站长春火车站停运了吗
  • 网吧可以做网站吗文字控图片在线制作
  • FC红白机游戏下载:1000多款FC小游戏打包下载
  • 实体店做网站有用吗新郑建设局网站
  • 长沙市建设网站网站建设平台接单
  • 网站改版什么意思免费做网站网站
  • 北京哪家公司做网站好网站开发的毕业周记
  • 为什么Java不支持多继承