MySQL中replace into详解、批量更新、不存在插入存在则更新、replace into的坑

news2024/11/26 10:17:48

文章目录

  • 一、replace into原理
  • 二、`replace into`的三种形式
  • 三、replace into 使用案例
    • 3.1、replace into values
      • 3.1.1、只有主键且主键冲突
      • 3.1.2、有主键有唯一索引且主键冲突
      • 3.1.3、有主键有唯一索引且唯一索引冲突(有坑)
      • 3.1.4、有主键有唯一索引且与一条主键冲突与另一条唯一键冲突(有坑)
    • 3.2、replace into select
    • 3.3、replace into set
      • 3.3.1、唯一索引不重复
      • 3.3.2、唯一索引重复
  • 四、replace into与on duplicate key update的区别
  • 五、replace into的坑
    • 5.1、replace into与自动更新时间的坑
    • 5.2、replace into用唯一索引更新时会导致自增值+1
    • 5.3、replace into同时有主键或唯一索引冲突时可能会删除多条记录

官网地址:https://dev.mysql.com/doc/refman/8.0/en/replace.html

以下内容基于mysql 8.0版本进行讲解。

replace into与on duplicate key update在一定程度上都能实现无记录时插入,有记录时更新这个需求。但是强烈推荐使用on duplicate key update 原因见下方两者的区别。replace into的坑太多,若要使用请详细阅读本文。

一、replace into原理

replace into 跟 insert 功能类似,不同点在于:replace into 首先尝试插入数据到表中, 1. 如果发现表中已经有此行数据(根据主键或者唯一索引判断)则先删除此行数据,然后插入新的数据。 2. 否则,直接插入新数据。

要注意的是:插入数据的表必须有主键或者是唯一索引!否则的话,replace into与insert into功能一致,会直接插入数据,这将导致表中出现重复的数据。

如果归纳一下 REPLACE INTO 语句的执行规则,基本会有以下几种情况:

  1. 当表没有主键和唯一键时,REPLACE INTO 相当于普通的 INSERT 操作;binlog 记录事件为 INSERT;返回影响行数为 INSERT 的数量。
  2. 当表有主键没有唯一键时,REPLACE INTO 插入记录与主键冲突时会进行 DELETE+INSERT 操作;binlog 记录事件为 UPDATE;返回影响行数为 DELETE+INSERT 的数量;如果主键自增,则 AUTO_INCREMENT 值不变。
  3. 当表有唯一键没有主键时,REPLACE INTO 插入记录与唯一键冲突时会进行 DELETE+INSERT 操作;binlog 记录事件为 UPDATE;返回影响行数为 DELETE+INSERT 的数量。
  4. 当表同时存在主键和唯一键时,REPLACE INTO 插入记录与主键冲突的时候进行 DELETE+INSERT 操作;binlog 记录事件为 DELETE+INSERT;返回影响行数为 DELETE+INSERT 的数量。如果主键自增,则 AUTO_INCREMENT 值不变。
  5. 当表同时存在主键和唯一键时,REPLACE INTO 插入记录与唯一键冲突的时候进行 DELETE+INSERT 操作;binlog 记录事件为 UPDATE;返回影响行数为 DELETE+INSERT 的数量。如果主键自增,则新插入的这条记录的主键会变成最新 AUTO_INCREMENT 的值,而对应的 AUTO_INCREMENT 值会 +1
  6. 当表同时存在主键和唯一键时,REPLACE INTO 插入记录与一条记录主键和一条记录唯一键都冲突的时候进行 DELETE+INSERT 操作;binlog 记录事件为 DELETE+UPDATE;返回影响行数为 DELETE*2+INSERT 的数量。

第五点会有副作用:见本文《3.1.3、有主键有唯一索引且唯一索引冲突(有坑)》
第六点会有副作用:见本文《3.1.4、有主键有唯一索引且与一条主键冲突与另一条唯一键冲突(有坑)》

总结

以下总结replace into时可能会遇到的场景
pk:主键 uk:唯一索引

  • 无pk无uk
场景replace into时相当于replace into在binlog中的表现形式返回影响行数
无pk无ukinsertinsertinsert行数
  • 只有pk
场景replace into时相当于replace into在binlog中的表现形式返回影响行数
pk冲突delete+insertupdatedelete+insert行数
pk不冲突insertinsertinsert行数
  • 只有uk
场景replace into时相当于replace into在binlog中的表现形式返回影响行数
uk冲突delete+insertupdatedelete+insert行数
  • 有pk有uk
场景replace into时相当于replace into在binlog中的表现形式返回影响行数
pk冲突 uk不冲突delete + insertdelete + insertdelete+insert行数
pk不冲突 uk冲突delete + insertupdatedelete+insert行数
pk冲突 uk冲突delete + insertdelete+insertdelete+insert行数
pk不冲突 uk不冲突insertinsertinsert行数

二、replace into的三种形式

1. replace into tbl_name(col_name, ...) values(...)

2. replace into tbl_name(col_name, ...) select ...

3. replace into tbl_name set col_name=value, ...

第一种形式相似于insert into的用法,

第二种replace select的用法也相似于insert select,这种用法并不必定要求列名匹配,事实上,MYSQL甚至不关心select返回的列名,它需要的是列的位置。例如,replace into tb1( name, title, mood) select rname, rtitle, rmood from tb2; 这个例子使用replace into从 tb2中将全部数据导入tb1中。

第三种replace set用法相似于update set用法,使用一个例如“SET col_name = col_name + 1”的赋值,则对位于右侧的列名称的引用会被做为DEFAULT(col_name)处理。所以,该赋值至关于SET col_name = DEFAULT(col_name) + 1。

前两种形式用的多些。其中 “into” 关键字能够省略,不过最好加上 “into”,这样意思更加直观。另外,对于那些没有给予值的列,MySQL 将自动为这些列赋上默认值。

三、replace into 使用案例

3.1、replace into values

3.1.1、只有主键且主键冲突

当只有主键且主键冲突时,会执行delete+insert操作

如下sql:

drop table if exists user_test;
create table user_test(
	id int primary key auto_increment comment '主键',
	name varchar(30)  not null comment '姓名',
	update_time timestamp on update CURRENT_TIMESTAMP comment '更新时间'
) comment '测试表';

insert into user_test(name,update_time) value ('zhangsan','2000-01-01 00:00:00');

在这里插入图片描述
此时执行replace into

replace into user_test(id,name) value (1,'zhangsan');

在这里插入图片描述
上图可以看出执行replace into之后,返回的受影响条数是2,且update_time的字段被更新为空了。由此证明replace into时当只有主键且主键冲突时执行了delete+insert操作。

注意: 当时间字段设置自动更新后,若没有设置默认值,replace into更新时需要手动赋予时间字段,否则会插入为空。

3.1.2、有主键有唯一索引且主键冲突

当有主键有唯一索引且主键冲突时,会执行delete+insert操作

drop table if exists user_test;
create table user_test(
	id int primary key auto_increment comment '主键',
	name varchar(30) unique not null comment '姓名',
	update_time timestamp on update current_timestamp comment '更新时间'
) comment '测试表';

insert into user_test(name,update_time) value ('zhangsan','2000-01-01 00:00:00');

replace into user_test(id,name) value (1,'lisi');

在这里插入图片描述
上图可以看出执行replace into之后,返回的受影响条数是2,且update_time的字段被更新为空了。由此证明replace into时当有主键有唯一索引且主键冲突时执行了delete+insert操作。

3.1.3、有主键有唯一索引且唯一索引冲突(有坑)

当有主键有唯一索引且唯一索引冲突时,会执行delete+insert操作,且AUTO_INCREMENT自增1

drop table if exists user_test;
create table user_test(
	id int primary key auto_increment comment '主键',
	name varchar(30) unique not null comment '姓名',
	update_time timestamp on update current_timestamp comment '更新时间'
) comment '测试表';

insert into user_test(name,update_time) value ('zhangsan','2000-01-01 00:00:00');

在这里插入图片描述
此时执行replace into语句

replace into user_test(name) value ('zhangsan');

在这里插入图片描述
上图可以看出执行replace into之后,返回的受影响条数是2,且update_time的字段被更新为空了。由此证明replace into时当有主键有唯一索引且唯一索引冲突时执行了delete+insert操作。

注意: 唯一索引冲突时会带来副作用,主键id被改变了。由于主键设置了自增,所以当唯一索引冲突时导致AUTO_INCREMENT的值自增1。

3.1.4、有主键有唯一索引且与一条主键冲突与另一条唯一键冲突(有坑)

当有主键与唯一索引时,若replace into与其中一条主键冲突、与另一条记录唯一索引冲突,此时执行delete+insert操作。注意:此时受影响的条数是3,且会删除两条数据,可能会有坑

drop table if exists user_test;
create table user_test(
	id int primary key auto_increment comment '主键',
	name varchar(30) unique not null comment '姓名',
	update_time timestamp on update current_timestamp comment '更新时间'
) comment '测试表';

insert into user_test(id,name,update_time) values
(1,'zhangsan','2000-01-01 00:00:00'),
(2,'lisi','2000-01-01 00:00:00');

replace into user_test(id,name) value (1,'lisi');

在这里插入图片描述
上图可以看出执行replace into之后,返回的受影响条数是3。

注意: 在该场景下会删除2条数据,然后插入1条数据,所以可能会造成坑,需要特别注意。

3.2、replace into select

语法类似insert into select

示例:
replace into t(id, update_time) select 1, now();
replace into tb1( name, title, mood) select rname, rtitle, rmood from tb2;

3.3、replace into set

表结构如下:

drop table if exists user_test;
create table user_test(
	id int primary key auto_increment comment '主键',
	name varchar(30) unique not null comment '姓名',
	age int default 2 comment '年龄',
	sex varchar(10) comment '性别:男、女'
) comment '测试表';

在这里插入图片描述

其中: name为唯一索引,age默认值是2

3.3.1、唯一索引不重复

执行以下sql插入第一条数据

replace into user_test set name = 'zhangsan',age = age+1, sex = '男';

在这里插入图片描述

可以看到age=3是因为age=default(age)+1,默认age=2然后又+1所以是3;若age字段建表时没有设置默认值则上述sql执行完后age为null。

3.3.2、唯一索引重复

接着上面的示例,运行以下sql

replace into user_test set name = 'zhangsan',age = age+1;

在这里插入图片描述

我们看到id=1的数据被删除了,新增了一条id=2的数据;它的sex字段的值没有继承第一条数据的值,age属性的值也只是由默认值决定,与上一条的值无关。

由此证明结论:

  1. 在没有唯一键/主键重复时,replace into所做的事情就是新添加一个条目,条目各个属性的值与运行的语句内容有关。
  2. 在有唯一键/主键重复时,replace into所做的事情就是
  • 直接删除掉那条重复的旧条目
  • 然后新添加一个条目。

新条目各个属性的值只取决于运行的语句内容,与被删除的旧条目的值无关。

四、replace into与on duplicate key update的区别

on duplicate key update更多内容参见《MySQL中ON DUPLICATE KEY UPDATE的介绍与使用、批量更新、存在即更新不存在则插入 – 五月天的尾巴》

replace into与on duplicate key update在一定程度上都能实现无记录时插入,有记录时更新这个需求。但是强烈推荐使用on duplicate key update 原因如下:

  1. replace into在唯一索引冲突时,会删除原记录,然后新增一条记录,如果主键id是自增的会导致主键被改变; 而on duplicate key update在唯一索引冲突时是更新原记录,主键不变。
  2. replace into唯一索引冲突时会导致主键自增值增加,但由于 binlog 事件记录为 UPDATE 会导致主从环境中表的 AUTO-INCREMENT 值不同,从库执行 UPDATE 事件并不会导致 AUTO-INCREMENT 值增加,所以从库表的 AUTO-INCREMENT 值会小于等于当前表的最新记录主键,当发生主从切换时向新的主库插入记录就会报 duplicate key 错误。

鉴于此,很多使用 REPLACE INTO 的场景,实际上需要的是 INSERT INTO … ON DUPLICATE KEY UPDATE(虽然也会增加自增值,但是不会出现从库表的 AUTO-INCREMENT 值会比当前表的最新记录主键小的情况),与 ‘REPLACE INTO …’ 不同,它只是更新重复行上的值,没有删除,也就不会导致原有主键值的变化。

1:replace into
2:on duplicate key update

一,两者在数据库中无记录时都执行插入操作;在数据库中有记录时都执行“更新”操作。
二,二者在判断有无记录时,都是根据表里的主键或唯一索引。
三,检索到存在记录时,1是先删除原记录,再插入新记录;而2是保持原记录不变,更新指定的字段。

如表中有如下记录,其中id是自增主键,col1是唯一索引:
(id, col1, col2,col3)= (1, a,b,c)

执行
replace into tabelname(col1, col2) values (a,d)
则表中数据变为
(id, col1, col2,col3)= (2, a,d,null)
原记录完全删除,id发生自增。

执行
insert into tablename(col1) values (a)
on duplicate key update col2=d
则表中数据变位
(id, col1, col2,col3)= (1, a,d,c)
col3保持不变,id未自增,不过在插入下一条记录时,id会跳跃。

五、replace into的坑

5.1、replace into与自动更新时间的坑

replace into在有主键或唯一索引冲突时,会执行delete+insert操作,若字段设置了自动更新,需要手动设置时间或者字段设置默认时间,否则时间字段会插入为空

如下sql:

drop table if exists user_test;
create table user_test(
	id int primary key auto_increment comment '主键',
	name varchar(30)  not null comment '姓名',
	update_time timestamp on update CURRENT_TIMESTAMP comment '更新时间'
) comment '测试表';

insert into user_test(name,update_time) value ('zhangsan','2000-01-01 00:00:00');

在这里插入图片描述
此时执行replace into

replace into user_test(id,name) value (1,'zhangsan');

在这里插入图片描述
上图可以看出执行replace into之后,update_time的字段被更新为空了。

解决方案

# 方案一:建表时设置字段有默认时间
create table user_test(
	id int primary key auto_increment comment '主键',
	name varchar(30)  not null comment '姓名',
	update_time timestamp default current_timestamp on update CURRENT_TIMESTAMP comment '更新时间'
) comment '测试表';

# 方案二:replace into时手动设置时间
replace into user_test values(1,'zhangsan',now());

5.2、replace into用唯一索引更新时会导致自增值+1

见本文《3.1.3、有主键有唯一索引且唯一索引冲突(有坑)》

5.3、replace into同时有主键或唯一索引冲突时可能会删除多条记录

注意:使用replace into时只能用主键更新或者唯一键更新,二选其一。若同时都冲突了,可能会导致异常

见本文《3.1.4、有主键有唯一索引且与一条主键冲突与另一条唯一键冲突(有坑)》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1530958.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

centos7磁盘管理,lvm挂载、扩容

一、centos7 磁盘挂载 默认盘符格式 centos7 默认文件格式xfscentos6 默认文件格式ext4centos5 默认文件格式ext3 1、/dev/vdb和/dev/mapper/lvm-data对比 1)/dev/vdb /dev/vdb通常表示一个裸的块存储设备,比如一个硬盘或者虚拟机中的一个虚拟硬盘。…

c语言综合练习题

1.编写程序实现键盘输入一个学生的学分绩点 score&#xff08;合法的范围为:1.0—5.0&#xff09;&#xff0c;根据学生的学分绩点判定该学 生的奖学金的等级&#xff0c;判定规则如下表所示。 #include <stdio.h>int main() {float score;printf("请输入学生的学分…

在Arm 虚拟硬件(AVH)部署深度学习OCR算法

AI算法的嵌入式部署 AI算法在独立的设备上运行其实就是行业内的嵌入式AI的概念, 大致过程如下: 开发AI模型, 2.对数据集进行处理, 3.训练AI模型并验证效果, 4.转成ONNX格式(ONNX:万金油中间格式,给模型优化和部署带来了更多可能性)或者借助libtorch或者TensorFlow来部署C++版…

FreeRTOS时间片调度

1. 时间片调度简介 同等优先级任务轮流地享有相同的 CPU 时间(可设置)&#xff0c; 叫时间片。在FreeRTOS中&#xff0c;一个时间片就等于SysTick 中断周期。 像我们的源码&#xff0c;滴答定时器是 1ms 中断一次&#xff0c;那么一个时间片的时间就是 1ms。可设置&#xff1a…

如何选择一款靠谱的短网址工具,避坑指南

选择一款靠谱的短网址服务是非常重要的。这不仅关乎到你的个人体验&#xff0c;更直接影响到你的业务发展和流量转化。想象一下&#xff0c;你精心策划了一场营销活动&#xff0c;通过短网址分享给了众多用户&#xff0c;然而因为短网址服务的不稳定&#xff0c;用户无法打开链…

多个线程交替打印ABC

多个线程交替打印ABC package 多个线程交替打印ABC;import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier;/*** Created with IntelliJ IDEA.** Author: AlenXu* Date: 2024/03/20/10:10* Description:*/ public class ThreadLoopP…

Hack The Box-Devvortex

目录 信息收集 nmap whatweb WEB web信息收集 wfuzz 漏洞探索 漏洞发现 反弹shell 提权 get user hashcat get root 信息收集 nmap 端口信息收集┌──(root?ru)-[~/kali/hackthebox] └─# nmap -p- 10.10.11.242 --min-rate 10000 Starting Nmap 7…

javase Set集合

Collection子接口2&#xff1a;Set 5.1 Set接口概述 Set接口是Collection的子接口&#xff0c;Set接口相较于Collection接口没有提供额外的方法 Set 集合不允许包含相同的元素&#xff0c;如果试把两个相同的元素加入同一个 Set 集合中&#xff0c;则添加操作失败。 Set集合…

红黑树简单介绍

1. 概念介绍 红黑树是一种自平衡二叉查找树&#xff0c;由于自平衡的特性&#xff0c;保证了最坏情况下在O&#xff08;logn&#xff09;时间复杂度内完成查找、增加、删除等操作&#xff0c;性能表现稳定。 在JDK中&#xff0c;TreeMap、TreeSet以及JDK1.8的HashMap底层都采用…

数据之王国:解析Facebook的大数据应用

引言 作为全球最大的社交媒体平台之一&#xff0c;Facebook拥有庞大的用户群体和海量的数据资源。这些数据不仅包括用户的个人信息和社交行为&#xff0c;还涵盖了广告点击、浏览记录等多方面内容。Facebook通过巧妙地利用这些数据&#xff0c;构建了强大的大数据应用系统&…

面向航天器大数据安全传输的发布/订阅系统设计

源自&#xff1a;系统工程与电子技术 作者&#xff1a;覃润楠 彭晓东 谢文明 惠建江 冯渭春 姜加红 “人工智能技术与咨询” 发布 摘 要 针对航天器试验任务过程监控的在轨故障诊断状态检测、健康状态评估与航天器寿命预测等多个环节中, 海量试验数据在传输、共享、处…

若依 无法导入表名过长的表格

原因 在mapper文件中&#xff0c;有很多转换的语句&#xff0c;使用的是nvarchar类型&#xff0c;nvarchar类型的长度很长&#xff0c;但是默认长度是30位。超过30位就会被截断 解决方案 找到mapper文件中所有对表名转换的地方&#xff0c;把长度扩大到100

电脑所有文档底色变绿?记好这4个方法就足够!

“这是怎么回事呢&#xff1f;怎么我的电脑里面所有文档底色都变绿了呢&#xff1f;我应该怎么操作才可以解决这个问题呀&#xff1f;” 在使用电脑的过程中&#xff0c;有时我们可能会遇到电脑所有文档底色变绿的情况。这种情况不仅影响了文档的阅读体验&#xff0c;还可能对视…

Visual Studio - 添加快捷键图标

Visual Studio - 添加快捷键图标 1. Text Editor Toolbar Options -> Add or Remove Buttons -> Customize2. Toolbars3. Commands -> Debug4. Add Command...References 1. Text Editor Toolbar Options -> Add or Remove Buttons -> Customize 2. Toolbars B…

【CSS】html滚动条相关

1.滚动条样式 ::-webkit-scrollbar {width: 10px;height: 10px;z-index: 101; } ::-webkit-scrollbar-thumb {border-radius: 5px;background: #cecece; } ::-webkit-scrollbar-track {// background: #f5f5f5be;background: rgba(33, 85, 163, 0); } ::-webkit-scrollbar-but…

热插拔技术详解(下)

4、热插拔导致的浪涌问题及其防治 &#xff08;1&#xff09;浪涌的概念 浪涌&#xff08;Electrical Surge&#xff09;顾名思义就是瞬间出现超出稳定值的峰值&#xff0c;它包括浪涌电压和浪涌电流。 浪涌电压是指超出正常工作电压的瞬间过电压&#xff1b;浪涌电流是指电源…

基于springboot+vue的疫情信息管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

AI助手 - 月之暗面 Kimi.ai

前言 这是 AI工具专栏 下的第四篇&#xff0c;这一篇所介绍的AI&#xff0c;也许是截至今天&#xff08;204-03-19&#xff09;国内可访问的实用性最强的一款。 今年年初&#xff0c;一直看到有人推荐 Kimi&#xff0c;不过面对雨后春笋般的各类品质的AI&#xff0c;说实话也有…

IP地址的分配:数字世界的地址规划者

在互联网的世界里&#xff0c;IP地址扮演着类似于房屋地址的角色&#xff0c;是用于标识和定位互联网上每个连接到网络的设备的唯一标识符。然而&#xff0c;这些IP地址并非随意分配&#xff0c;而是经过精心规划和管理的。本文将探讨IP地址的分配方式&#xff0c;揭示数字世界…

媒体邀约专访的意义?怎么做

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 媒体邀约专访是指企业、组织或个人主动邀请媒体进行专题访谈的一种公关活动。这种活动对于提升品牌形象、传播信息、增强公众认知度和信任度等方面都有重要作用。以下是媒体邀约专访的一…