mysql:如何实现插入或更新一条数据(对比 replace into 和 insert on duplicate key update)

79 篇文章 11 订阅

环境:

  • window10
  • mysql 8.0.25
  • DBeaver

参考:
《mysql:13.2.9 REPLACE Statement》
《mysql:13.2.6.2 INSERT … ON DUPLICATE KEY UPDATE Statement》
《博文:MySQL的INSERT ··· ON DUPLICATE KEY UPDATE使用的几种情况》
《博文:MYSQL中replace into的用法》

1. 常见问题:如何一条sql语句实现插入或更新?

在sqlserver中我们可以用 merge关键字实现(《sqlserver:merge关键字用法》)。

那么,在mysql中怎么实现呢?

mysql实现的功能稍微要弱一点,但也一般可用。
在sqlsever中我们可以根据直接where条件,当匹配到后就执行update,匹配不到就执行insert,但在mysql中我们不能写where条件,只能自动使用表的主键或唯一索引。

下面就看两种语法:replace into 和 insert on duplicate key update。

2. replace into 能满足需求吗?不能!

其实这个语句不能使用插入或更新。
它的功能是替代,即:如果有的话就先删除,然后再插入。

看下面的例子:

create table test(
	id int primary key,
	name varchar(50),
	uno varchar(50) unique,
	addr varchar(50)
)
insert into test(id,name,uno,addr) values(1,'小明','001','天明路'),(2,'小红','002','天明路2'),(3,'小刚','003','天明路3');

-- 因为不存在,这里执行插入
replace into test(id,name,uno,addr) values(4,'小军','004','天明路4')
select * from test

此时的表数据如下:
在这里插入图片描述
下面执行replace语句:

-- 主键和unique索引都重复了,这将导致删除两条数据后再插入一条,影响3条数据
replace into test(id,name,uno,addr) values(1,'替换两个','002','天明路222')
select  * from test

在这里插入图片描述

可以看到,上面删除了2条数据,只插入了一条,它不能满足我们的需求。

3. insert on duplicate key update 可以满足功能

从字面上看,这哥语句时先尝试插入,当遇到重复主键或索引的时候进行update操作。应该是满足我们需求的。

先看下面的示例:

create table test(
	id int primary key,
	name varchar(50),
	uno varchar(50) unique,
	addr varchar(50)
)
insert into test(id,name,uno,addr) values(1,'小明','001','天明路'),(2,'小红','002','天明路2'),(3,'小刚','003','天明路3');
select * from test

此时数据:
在这里插入图片描述
之心插入或更新:

-- 插入时故意让主键和unique索引都重复 观察效果
insert into test(id,name,uno,addr) values(2,'小红2','001','天明路55') ON DUPLICATE KEY update  name='56'
select * from test

观察数据:
在这里插入图片描述
可以看到,插入时,虽然主键和唯一索引uno列都重复了,但mysql以主键为主。
另外,mysql更新的时候只会作用于一条重复的行,这在mysql文档上有说明:
在这里插入图片描述
但mysql文档上并没有说明,当主键和其他唯一索引都冲突的时候以谁为主。
不过我试验了多次得到的结果都是以主键为主!

4. 总结

如果我们想实现插入或更新一条数据的话,我们可以约定这个表必须存在主键,然后使用 insert on duplicate key update 实现。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jackletter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值