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

五、总结

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

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

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

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

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

感谢您的支持和理解!

相关推荐
TG:@yunlaoda360 云老大26 分钟前
华为云国际站代理商GES的图引擎服务有哪些优势?
服务器·数据库·华为云
毕设源码-朱学姐28 分钟前
【开题答辩全过程】以 基于SpringBoot的中医理疗就诊系统为例,包含答辩的问题和答案
java·spring boot·后端
上进小菜猪5 小时前
从人工目检到 AI 质检-YOLOv8 驱动的 PCB 缺陷检测系统【完整源码】
后端
Coder_Boy_6 小时前
基于SpringAI的智能平台基座开发-(六)
java·数据库·人工智能·spring·langchain·langchain4j
热爱专研AI的学妹6 小时前
数眼搜索API与博查技术特性深度对比:实时性与数据完整性的核心差异
大数据·开发语言·数据库·人工智能·python
hopsky7 小时前
ShardingSphere功能简介
数据库·sql
阿狸远翔7 小时前
Protobuf 和 protoc-gen-go 详解
开发语言·后端·golang
talenteddriver7 小时前
mysql: MySQL索引和排序相关名词概念汇总
数据库·mysql
间彧7 小时前
Vert.x与Spring框架:开发效率与团队学习成本深度对比
后端
间彧7 小时前
Vert.x与传统Spring框架在性能、并发处理方面有哪些差异
后端