数据库技巧:REPLACE INTO的高效替换方法

在Hibernate里面有一个非常好用的方法,是由org.hibernate.Session提供的,这个方法的名称叫做saveOrUpdate

一些小伙伴发现了MySQL里面有一种写法叫做REPLACE INTO

有一些人会以为REPLACE INTOsaveOrUpdate一样,实际这是错误的,本文带你详细了解一下REPLACE INTO语句。

一、认识REPLACE INTO

REPLACE INTO 是 SQL 中用于插入或更新数据的一种语句,它结合了 INSERTUPDATE 的功能,主要用于处理重复数据的情况。但是这个UPDATE有点不一样,我们仔细看看。

官方介绍点这里

1.1 基本语法

REPLACE INTO 的基本语法如下:

sql 复制代码
REPLACE INTO table_name (column1, column2, ..., columnN)
VALUES (value1, value2, ..., valueN);

或者:

sql 复制代码
REPLACE INTO table_name
SET column1 = value1, column2 = value2, ..., columnN = valueN;

1.2 简单使用

  • 现在我们有这么一张用户表,建表语句如下:
sql 复制代码
CREATE TABLE `user_info` (
  `id` varchar(80) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户id',
  `risk_score` int NOT NULL DEFAULT '0' COMMENT '风险评分 0-100 (不可超出该范围)',
  `risk_level` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0-安全 1-低风险 2-中风险 3-高风险',
  `register_time` datetime NOT NULL COMMENT '注册时间',
  `created` datetime NOT NULL COMMENT '创建时间(北京时间)',
  `updated` datetime DEFAULT NULL COMMENT '修改时间(北京时间)',
  `creator` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人',
  `updater` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '更新人',
  PRIMARY KEY (`id`),
  KEY `idx_updated` (`updated`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户安全信息表';
  • 我们先把表里面插入一行数据:
sql 复制代码
INSERT INTO `user_info`(`id`, `risk_score`, `risk_level`, `register_time`, `created`, `updated`, `creator`, `updater`) VALUES ('11-00762ef32f454892ad2ed7b2fc49d409', 20, 1, '2024-02-29 14:23:25', '2025-04-29 14:13:58', '2025-04-29 14:13:58', 'admin', 'admin');

插入结果如下:

  • 现在我们写一个REPLACE INTO语句,执行看看结果:
sql 复制代码
REPLACE INTO `user_info`(`id`, `risk_score`, `risk_level`, `register_time`, `created`, `updated`, `creator`, `updater`) VALUES ('11-00762ef32f454892ad2ed7b2fc49d409', 40, 1, '2024-02-29 14:23:25', '2025-04-30 14:13:58', '2025-04-30 14:13:58', 'admin30', 'admin30');

注意:这里我们很明显的可以看出来,所影响的行数是2

  • 查询原表记录如下:得到结果,表里面还是一条记录,为什么呢?

二、研究REPLACE INTO执行原理

上面1.2的简单使用,我们发现当执行1.2里面的语句的时候,所影响的行数是2,那么是不是所有的REPLACE INTO语句,影响行数都是2呢?

2.1 来个案例

  • 首先我们准备下面这么一条SQL:
sql 复制代码
REPLACE INTO `user_info`(`id`, `risk_score`, `risk_level`, `register_time`, `created`, `updated`, `creator`, `updater`) VALUES ('22-00762ef32f454892ad2ed7b2fc49d222', 20, 1, '2024-02-29 14:23:25', '2025-04-30 14:13:58', '2025-04-30 14:13:58', 'test', 'test');

执行之后我们得到的结果如下:可以很明显的看到,这条sql执行所影响的行数是1。

2.2 找原因

通过上面1.2和2.1里面的案例,我们发现,REPLACE INTO语句,有的时候影响行数是1,有的时候影响行数是2,那么为什么呢?

我们一起看看官方是怎么解释的:

官方文档有大量的详细的介绍(可以点击这里仔细看看);上面截图部分是我找的比较直白介绍的内容:

他说:当在MySQL使用REPLACE INTO语句的时候,

  • 1、首先尝试插入新行到表中;

  • 2、当由于主键或唯一索引发生 duplicate-key 错误而导致插入失败时

    • 先从表中删除具有 duplicate 键值的冲突行

    • 再次尝试将新行插入表中

到这里相信大家就知道为什么有的影响行数是1.有的影响行数是2了。说白了,REPLACE INTO 的主要功能是插入数据,但如果表中已经存在与插入数据的主键或唯一键冲突的记录,它会先删除旧记录,再插入新记录。所以他不是插入或者更新这种操作,切记。

三、存在即合理(哪些场景适用)

实际这个不用多说,大家理解了原理相比也能知道哪里使用合适,这里我罗列一些,大家实际业务按需求分析。

四、注意事项

使用 REPLACE INTO 语句时,有一些特别棒需要注意的事项,这些事项涉及语法、性能、数据完整性、事务处理等方面。

  • 依赖唯一性约束REPLACE INTO 依赖于表中的主键或唯一键约束。如果表中没有定义主键或唯一键,REPLACE INTO 将无法正确判断哪些记录是重复的,从而无法执行替换操作。

  • 删除和插入操作REPLACE INTO 实际上是先删除重复的记录,再插入新的记录。这意味着它会执行两次操作(删除 + 插入),可能会比单纯的 INSERTUPDATE 操作更耗时,尤其是在数据量较大的表中

  • 索引影响:删除和插入操作都会影响索引。删除操作会更新索引,插入操作也会更新索引,这可能会导致索引的维护成本增加,进而影响性能。

  • 外键约束:如果表中存在外键约束,删除操作可能会导致外键关联的完整性问题。例如,如果被删除的记录被其他表引用,可能会导致外键约束冲突。当然,谁家好人用外键啊,哈哈。

五、总结

REPLACE INTO 是一个强大的 SQL 语句,但在使用时需要注意其依赖的唯一性约束、性能影响、数据完整性问题以及事务处理等。在实际应用中,建议根据具体的业务需求和数据特点选择合适的操作方式,并在使用前进行充分的测试和验证。

另外:再次强调,他是插入或者删除插入,不是插入或者更新,别搞混了。

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

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

感谢您的支持和理解!

相关推荐
天天摸鱼的java工程师14 分钟前
如何实现一个红包系统,支持并发抢红包?
后端
稳妥API14 分钟前
Gemini 2.5 Pro vs Flash API:正式版对比选择指南,深度解析性能与成本平衡 - API易-帮助中心
后端
深栈解码19 分钟前
OpenIM 源码深度解析系列(十一):群聊系统架构与业务设计
后端
trow23 分钟前
Spring 手写简易IOC容器
后端·spring
山城小辣椒23 分钟前
spring-cloud-gateway使用websocket出现Max frame length of 65536 has been exceeded
后端·websocket·spring cloud
天天摸鱼的java工程师26 分钟前
谈谈你对 AQS(AbstractQueuedSynchronizer)的理解?
后端
鸡窝头on26 分钟前
Spring Boot 多 Profile 配置详解
spring boot·后端
风之旅人27 分钟前
开发必备"节假日接口"
java·后端·开源
鑫有灵溪29 分钟前
Redis 8 架构评估:企业级缓存方案的技术选型与实践指南
后端
用户26980484131930 分钟前
@PathVariable注解
后端