数据库技巧: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使用的问题,具体点击这里

五、总结

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

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

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

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

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

感谢您的支持和理解!

相关推荐
leobertlan7 小时前
2025年终总结
前端·后端·程序员
面向Google编程8 小时前
从零学习Kafka:数据存储
后端·kafka
马克Markorg8 小时前
常见的向量数据库和具有向量数据库能力的数据库
数据库
易安说AI8 小时前
Claude Opus 4.6 凌晨发布,我体验了一整晚,说说真实感受。
后端
易安说AI9 小时前
Ralph Loop 让Claude无止尽干活的牛马...
前端·后端
易安说AI9 小时前
用 Claude Code 远程分析生产日志,追踪 Claude Max 账户被封原因
后端
颜酱10 小时前
图结构完全解析:从基础概念到遍历实现
javascript·后端·算法
Coder_Boy_10 小时前
技术让开发更轻松的底层矛盾
java·大数据·数据库·人工智能·深度学习
helloworldandy10 小时前
使用Pandas进行数据分析:从数据清洗到可视化
jvm·数据库·python
数据知道12 小时前
PostgreSQL 故障排查:如何找出数据库中最耗时的 SQL 语句
数据库·sql·postgresql