数据库技巧:ON DUPLICATE KEY UPDATE的灵活处理

引用

在数据库数据插入遇到重复键冲突的时候,有的时候需要忽略继续插入,但是有的时候则需要更新。

在上一篇文章我介绍了怎么忽略继续插入数据库技巧:INSERT IGNORE的高效插入策略

这篇文章我将介绍一下怎么在数据库层面执行更新操作。

一、认识 ON DUPLICATE KEY UPDATE 语句

ON DUPLICATE KEY UPDATE 是 MySQL 提供的一个非常强大的功能,用于在插入数据时处理重复键冲突。它允许你在插入数据时指定,如果发生重复键冲突(如主键或唯一索引冲突),则执行更新操作,而不是报错。这种方式非常适合在需要"插入或更新"逻辑的场景中使用。

特点插入或更新

MySQL官方介绍

二、基本语法

ON DUPLICATE KEY UPDATE 的语法结构如下:

sql 复制代码
INSERT INTO table_name (column1, column2, ..., columnN)
VALUES (value1, value2, ..., valueN)
ON DUPLICATE KEY UPDATE
    column1 = value1,
    column2 = value2,
    ...,
    columnN = valueN;
  • INSERT INTO table_name:指定要插入数据的表。

  • VALUES:指定要插入的值。

  • ON DUPLICATE KEY UPDATE:如果在插入过程中发现唯一键冲突,则执行更新操作。

  • column1 = value1, column2 = value2, ... :指定在发生冲突时需要更新的字段及其新值。

三、工作原理

当执行 INSERT 语句时,如果插入的数据违反了表的唯一性约束(如主键或唯一索引),MySQL 会触发 ON DUPLICATE KEY UPDATE 子句中的更新操作,而不是报错。以下是其工作原理的详细说明:

3.1 插入数据

如果插入的数据没有违反唯一性约束,数据将正常插入。

3.2 更新数据

如果插入的数据违反了唯一性约束(如主键或唯一索引冲突),MySQL 会执行 ON DUPLICATE KEY UPDATE 子句中的更新操作。你可以指定需要更新的字段及其值。

3.3 返回值

ON DUPLICATE KEY UPDATE 的返回值是一个整数,表示操作的结果:

  • 返回值为 1:表示插入成功。

  • 返回值为 2:表示触发了更新操作。

  • 返回值为 n :表示成功插入了 n 行数据(在插入多行时)。

3.4 在MyBatis里面使用的案例

  • login_log_temp 表中按 loginDay 分组聚合后的数据插入到 extension_users 表中
sql 复制代码
<update id="insertOrUpdateUsers">
    insert into extension_users(loginDate, num)
    select loginDay,sum(loginCount) as num
      from login_log_temp
      group by loginDay
    on duplicate key update num = num + values(num)
</update>
  • 根据参数批量插入或者更新到phy_account_site_nick表里面
sql 复制代码
<insert id="insertPhyAccountSiteNick" parameterType="java.util.List">
    insert into phy_account_site_nick
    (
    account_uuid,
    site,
    nick,
    last_show_id,
    last_physical_start_date
    )
    values
    <foreach collection="list" item="item" separator=",">
        (
        #{item.accountId},
        #{item.site},
        #{item.nick},
        #{item.showId},
        #{item.physicalStartDate}
        )
    </foreach>
    ON DUPLICATE KEY UPDATE
    last_show_id = values(last_show_id),
    last_physical_start_date = values(last_physical_start_date)
</insert>

四、避坑(实际开发中,我们要尽量避免使用它)

虽然上面看着用起来非常爽,但是实际我们再实际开发过程中,会尽量避免使用ON DUPLICATE KEY UPDATE子句,特别是在大量或者频繁遇到DUPLICATE KEY的时候,程序会表现出严重的性能滑落。

下面是官网文档的介绍,也是让我们避免使用(注意:这个避免使用是有前提的)。

另外:在MySQL的官方bug列表中,也是有关于ON DUPLICATE KEY UPDATE使用的问题,具体点击这里

五、总结

写这篇文章我是看到有一些人老喜欢使用这个,但是实际随着业务的增长,后续会非常容易踩坑。

个人建议,还是慎用,尽量不用。

特别强调:在大量或频繁遇到重复键冲突时,会导致性能下降。

希望本文对您有所帮助。如果有任何错误或建议,请随时指正和提出。

同时,如果您觉得这篇文章有价值,请考虑点赞和收藏。这将激励我进一步改进和创作更多有用的内容。

感谢您的支持和理解!

相关推荐
Ghostbaby7 分钟前
eBPF 基础知识-如何构建BTF
后端
秋意零14 分钟前
【排坑指南】MySQL初始化后,Nacos与微服务无法连接??
运维·数据库·mysql·微服务·nacos·报错
SimonKing28 分钟前
集合的处理:JDK和Guava孰强孰弱?
java·后端·算法
Java微观世界32 分钟前
Java逻辑运算符完全指南:短路与、非短路或、异或的妙用,一篇搞定!
后端
星星电灯猴34 分钟前
数据差异的iOS性能调试:设备日志导出和iOS文件管理
后端
Ghostbaby39 分钟前
stack_traces 创建失败
后端
瀚海澜生40 分钟前
快速掌握使用redis分布式锁
后端
yz_518 Nemo1 小时前
Django项目实战
后端·python·django
麓殇⊙1 小时前
操作系统期末复习--操作系统初识以及进程与线程
java·大数据·数据库
胖头鱼不吃鱼1 小时前
Apipost 与 Apifox:API 协议功能扩展对比,满足多元开发需求
后端