当前位置: 代码网 > it编程>数据库>Mysql > MySQL中ON DUPLICATE KEY UPDATE优雅解决存在更新/不存在插入难题

MySQL中ON DUPLICATE KEY UPDATE优雅解决存在更新/不存在插入难题

2025年10月10日 Mysql 我要评论
前言在日常的数据库操作中,我们经常会遇到这样的场景:“如果数据存在,就更新它;如果不存在,就插入一条新的”。这种模式通常被称为 “upsert”(upd

前言

在日常的数据库操作中,我们经常会遇到这样的场景:“如果数据存在,就更新它;如果不存在,就插入一条新的”。这种模式通常被称为 “upsert”(update + insert)。在 mysql 中,实现 upsert 最优雅、最高效的方式之一就是使用 on duplicate key update 语法。

一、基本概念

1、什么是 on duplicate key update

on duplicate key update是 mysql 特有的一种 insert 语句扩展,当执行 insert 操作时,如果插入的数据与表中已有数据的主键(primary key)​或唯一索引(unique index)​发生冲突(即要插入的值与已有记录的主键或唯一索引值相同),则不执行插入操作,而是转而执行 update 操作,更新已存在的记录。

2、工作原理

尝试插入​:mysql 首先尝试按照正常的 insert 语句插入新记录

检查冲突​:在插入前,mysql 会检查是否存在与待插入数据主键或唯一索引冲突的记录

冲突处理​:

  • 如果没有冲突:正常插入新记录
  • 如果有冲突:不插入新记录,而是根据 on duplicate key update子句更新已存在的记录

3、基本语法

基本语法格式如下:

insert into table_name (column1, column2, ..., columnn)
values (value1, value2, ..., valuen)
on duplicate key update
    column1 = value1,
    column2 = value2,
    ...;

更常用的写法是使用 values() 函数来引用原本打算插入的值:

insert into table_name (column1, column2, ..., columnn)
values (value1, value2, ..., valuen)
on duplicate key update
    column1 = values(column1),
    column2 = values(column2),
    ...;

触发条件:只有当插入操作违反了 主键(primary key) 或 唯一索引(unique index) 约束时,update 部分才会被执行

二、使用场景

1、计数器更新

最常见的应用场景是实现计数器功能,如文章浏览量、点赞数等

insert into article_views (article_id, view_count) 
values (123, 1) 
on duplicate key update 
	view_count = view_count + 1;

2、配置项更新

当需要更新或插入配置项时

insert into system_config (config_key, config_value, last_updated) 
values ('site_title', 'my website', now()) 
on duplicate key update 
	config_value = values(config_value), last_updated = now();

3、购物车商品更新

添加商品到购物车,已存在则更新数量

insert into shopping_cart (user_id, product_id, quantity) 
values (123, 456, 2)
on duplicate key update 
    quantity = quantity + values(quantity),
    added_at = current_timestamp;

必须添加主键或唯一索引,否则on duplicate key update将不会触发,语句会正常执行插入操作(如果无其他错误)

三、高级用法

1、条件更新

在 on duplicate key update子句中使用条件表达式

-- 这个例子只在新的价格更低时才更新价格
insert into products (product_id, price, last_updated) 
values (101, 99.99, now()) 
on duplicate key update 
    price = if(values(price) < price, values(price), price),
    last_updated = now();

2、多表关联

虽然不能直接在 on duplicate key update中使用多表,但可以结合子查询

insert into user_stats (user_id, login_count) 
select 123, 1 from dual
where not exists (select 1 from users where id = 123)
on duplicate key update 
	login_count = login_count + 1;

3、批量操作优化

对于大量数据的批量插入/更新,考虑以下优化

insert into log_entries (user_id, action, timestamp) 
values 
    (1, 'login', now()),
    (2, 'view', now()),
    (3, 'purchase', now())
on duplicate key update 
    action = values(action), 
    timestamp = values(timestamp);

当表有多个唯一约束时,任何唯一键冲突都会触发update

四、其他处理冲突的方案

1、replace into

实际上是先delete再insert,主键会有变化

replace into users (email, name, login_count) 
values ('test@example.com', 'test user', 1);

2、insert ignore

冲突时直接忽略,不更新

insert ignore into users (email, name) 
values ('test@example.com', 'test user');

到此这篇关于mysql中on duplicate key update优雅解决存在更新/不存在插入难题的文章就介绍到这了,更多相关mysql on duplicate key update内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com