引用
在数据库数据插入遇到重复键冲突的时候,有的时候需要忽略继续插入,但是有的时候则需要更新。
在上一篇文章我介绍了怎么忽略继续插入数据库技巧:INSERT IGNORE的高效插入策略。
这篇文章我将介绍一下怎么在数据库层面执行更新操作。
一、认识 ON DUPLICATE KEY UPDATE 语句
ON DUPLICATE KEY UPDATE
是 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
使用的问题,具体点击这里
五、总结
写这篇文章我是看到有一些人老喜欢使用这个,但是实际随着业务的增长,后续会非常容易踩坑。
个人建议,还是慎用,尽量不用。
特别强调:在大量或频繁遇到重复键冲突时,会导致性能下降。
希望本文对您有所帮助。如果有任何错误或建议,请随时指正和提出。
同时,如果您觉得这篇文章有价值,请考虑点赞和收藏。这将激励我进一步改进和创作更多有用的内容。
感谢您的支持和理解!