百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

INSERT INTO 和 ON DUPLICATE KEY UPDATE,数据写入的最佳搭档?

ztj100 2025-05-05 20:15 1 浏览 0 评论

数据库里,数据插入可不只是 INSERT INTO 这么简单,写入时如果遇到主键冲突怎么办?直接报错?还是自动更新?今天聊聊 INSERT INTO 和 ON DUPLICATE KEY UPDATE,看看这两个能咋配合,顺便对比 REPLACE INTO,弄明白它们的区别,别再用错了!

INSERT INTO:最基础的数据插入

这个大家应该都用过,往表里新增数据,写法很简单:

但 INSERT INTO 有个问题,如果 id=4 已经存在,直接报错,根本插不进去。

这时候,得换个办法解决,不能让程序报错卡住。

ON DUPLICATE KEY UPDATE:有就更新

如果 id=4 已经存在,想更新数据,而不是报错,试试这个:

这个写法的逻辑:

1. id=4 不存在,就正常插入

2. id=4 已存在,就更新 age,而不会删除旧数据

这个方式很安全,不会误删数据!

和 REPLACE INTO 最大的不同在于,ON DUPLICATE KEY UPDATE 不会先删再插,所以数据完整性不会被破坏。

REPLACE INTO:删除旧数据再插入

如果用 REPLACE INTO,id=4 这条数据会被整个删掉,然后重新插入:

问题来了,REPLACE INTO 可能会误删数据!

比如表里有 created_at 字段,REPLACE INTO 会让它重置:

再执行:

created_at 被重置了! 因为 REPLACE INTO 是先删后插,相当于旧数据被删掉,再重新插入,所有默认字段都会重置。

ON DUPLICATE KEY UPDATE 就不会有这个问题!

性能对比

看看 INSERT INTO、ON DUPLICATE KEY UPDATE 和 REPLACE INTO 在影响行数上的区别:

ON DUPLICATE KEY UPDATE 更新时影响行数是 2,因为它尝试插入了一次,然后更新了一次。

REPLACE INTO 影响行数也是 2,但它是 1 次删除 + 1 次插入,风险更大。

简单总结:

只插入新数据,INSERT INTO 就够了。

需要更新但不能丢数据,ON DUPLICATE KEY UPDATE 是最佳选择。

数据没关系,随时可以重写,REPLACE INTO 适合临时表或缓存表。

实践应用场景

1. 订单系统

用户下单时,想确保订单号唯一,但可以更新支付状态:

这个方法:

如果订单号不存在,插入新订单

如果订单号已存在,只更新 status,不会删掉原来的订单信息

2. 用户登录时间更新

更新用户最后一次登录时间:

这比 REPLACE INTO 安全,因为不会把 users 里的其他字段误删。

3. 数据同步

如果定期同步用户信息,ON DUPLICATE KEY UPDATE 是最好的选择:

数据有变化就更新,没变化就不动,比 REPLACE INTO 高效又安全。

看似简单,实则暗藏玄机。直接 INSERT INTO?还是 ON DUPLICATE KEY UPDATE?还是用 REPLACE INTO?如果你还在纠结,今天这篇就给你讲透,让你的 MySQL 写入操作又快又安全。

1. INSERT INTO:最基础但最容易报错的插入方式

INSERT INTO 估计大家用得最多,往表里加一条新数据,写法简单直白:

执行后:

但是,如果 id=4 已经存在,再次执行这条 SQL,直接报错:

这意味着,如果 ID 是唯一的,MySQL 不允许重复插入。这种情况下,你要么手动检查 ID 是否存在,要么用更聪明的方式来解决,比如 ON DUPLICATE KEY UPDATE。

2. ON DUPLICATE KEY UPDATE:有就更新

如果 id=4 已经在数据库里了,我们可以用 ON DUPLICATE KEY UPDATE 让 MySQL 自动更新,而不会报错:

执行后:

工作原理

1. 如果 id=4 不存在,直接插入新数据

2. 如果 id=4 已存在,更新 age 字段的值,而不会删除其他数据

这个方式的好处是,不会误删其他字段的数据,比 REPLACE INTO 安全得多。

3. REPLACE INTO:它会误删数据!

REPLACE INTO 和 ON DUPLICATE KEY UPDATE 很像,但有个致命问题:它的逻辑是先删再插,所以可能会误删数据:

执行后:

乍一看没啥问题,但如果你的 users 表里有 created_at 这种自动生成的时间字段,那就惨了:

然后执行:

created_at 变了,这是因为 REPLACE INTO 先删了 id=4 这条数据,再插入一条新数据,相当于 created_at 也被重置了。

4. 性能对比

来看 INSERT INTO、ON DUPLICATE KEY UPDATE 和 REPLACE INTO 的影响行数:

ON DUPLICATE KEY UPDATE:更新时影响行数是 2,因为尝试插入了一次,然后更新了一次。

REPLACE INTO:影响行数也是 2,但它是 1 次删除 + 1 次插入,容易误删数据!

如果数据要保持完整性,ON DUPLICATE KEY UPDATE 更稳妥。

如果数据可随意覆盖,REPLACE INTO 适合临时数据,但不建议用于关键业务。

5. 实际应用

① 订单系统

如果用户下单,订单号唯一,可以用 ON DUPLICATE KEY UPDATE 确保订单状态能更新:

订单不存在 → 插入新订单

订单已存在 → 更新 status,不会误删数据

② 用户最后登录时间

更新用户的 last_login:

不会误删 users 里的其他字段,比 REPLACE INTO 安全。

③ 数据同步

定期更新用户信息:

数据有变化就更新,没变化就不动,比 REPLACE INTO 高效又安全。

REPLACE INTO 最好少用,小心丢数据!

数据库写入,看似简单,其实有很多“坑”——特别是 REPLACE INTO,它看起来和 INSERT INTO ... ON DUPLICATE KEY UPDATE 差不多,但本质上是先删除再插入,可能会导致数据丢失。今天就来聊聊 REPLACE INTO,为什么它很危险,什么时候可以用,以及更好的替代方案。

1. REPLACE INTO 的工作方式

REPLACE INTO 的基本作用是“如果数据已存在,就删掉旧数据,再插入新数据”。

它和 ON DUPLICATE KEY UPDATE 的主要区别是:

ON DUPLICATE KEY UPDATE:有就更新,没有就插入,原有数据不受影响。

REPLACE INTO:如果主键或唯一索引冲突,先删除原数据,再插入新数据。

来看个例子

数据表结构

初始数据

执行 REPLACE INTO

问题来了!

id=1 的那一行先被删掉了,再插入一条新的记录。

created_at 也被重置了,之前的创建时间丢了!

如果有其他依赖这条数据的表,可能会导致数据丢失或不一致。

2. REPLACE INTO 为什么危险?

① 会触发 DELETE 语句

REPLACE INTO 不是简单的更新,而是先删除再插入,相当于执行了以下 SQL:

问题

删除会触发外键约束,如果这条数据被其他表引用,可能导致错误。

删除操作会影响事务,如果事务回滚,数据可能无法恢复。

删除会重置所有自动生成字段,如 created_at,或者自增 ID(如果主键是 AUTO_INCREMENT)。

② 影响行数不同

MySQL 里,我们经常用 ROW_COUNT() 或者 影响行数 来判断 SQL 执行情况:

ON DUPLICATE KEY UPDATE:如果更新了一行,影响行数是 2(尝试插入 + 更新)。

REPLACE INTO:如果替换了一行,影响行数是 2(删除 + 插入)。

区别在于:REPLACE INTO 是物理删除+新插入,ON DUPLICATE KEY UPDATE 只是更新数据,不会删掉原来的内容!

③ 外键约束可能出问题

假设有 orders 表,里面有 user_id 关联 users:

如果 REPLACE INTO 先删除 users 里的 id=1,orders 里的 user_id=1 就会变成无效外键,数据库可能会报错,甚至数据丢失。

④ 触发器(Triggers)可能执行异常

如果你的表上有 BEFORE DELETE 或 AFTER DELETE 触发器,REPLACE INTO 执行时会意外触发这些触发器,导致程序逻辑异常。

3. 什么场景适合用 REPLACE INTO?

虽然 REPLACE INTO 有很多风险,但也有一些适用场景:

临时数据或缓存表:比如存储每日数据快照,不在乎数据变更。

不带外键的简单表:如果表没有外键,REPLACE INTO 的副作用小一些。

日志或审计表:如果要保留最新状态,而不在意旧数据。

示例:

这样每天只保留最新的统计数据,之前的数据可以被覆盖,不影响其他表。

4. 更好的替代方案

① ON DUPLICATE KEY UPDATE

如果只是想更新已有数据,ON DUPLICATE KEY UPDATE 是更好的选择:

不会删除旧数据

不会触发 DELETE 触发器

不会影响外键完整性

② INSERT IGNORE

如果你只想防止主键冲突,而不进行更新,可以用 INSERT IGNORE:

如果 id=1 已存在,这条 SQL 什么都不做

不会触发 DELETE

不会影响已有数据

总结

REPLACE INTO 的风险

1. 先删除再插入,可能导致数据丢失。

2. 会触发 DELETE 语句,影响外键完整性。

3. 会误删自动生成字段(如 created_at)。

4. 影响行数容易误导程序逻辑。

5. 可能触发 DELETE 触发器,导致意外逻辑错误。

更好的替代方案

需求 推荐方案

想更新已有数据,不删除原数据 ON DUPLICATE KEY UPDATE

想防止插入重复数据,但不报错 INSERT IGNORE

需要覆盖数据,但表很简单 REPLACE INTO

如果你的表里有外键、触发器或者自动生成的时间字段,尽量别用 REPLACE INTO,用 ON DUPLICATE KEY UPDATE 更安全!

有疑问?留言聊聊!你在实际项目中用过 REPLACE INTO 吗?有没有踩过坑?

相关推荐

告别手动操作:一键多工作表合并的实用方法

通常情况下,我们需要将同一工作簿内不同工作表中的数据进行合并处理。如何快速有效地完成这些数据的整合呢?这主要取决于需要合并的源数据的结构。...

【MySQL技术专题】「优化技术系列」常用SQL的优化方案和技术思路

概述前面我们介绍了MySQL中怎么样通过索引来优化查询。日常开发中,除了使用查询外,我们还会使用一些其他的常用SQL,比如INSERT、GROUPBY等。对于这些SQL语句,我们该怎么样进行优化呢...

9.7寸视网膜屏原道M9i双系统安装教程

泡泡网平板电脑频道4月17日原道M9i采用Win8安卓双系统,对于喜欢折腾的朋友来说,刷机成了一件难事,那么原道M9i如何刷机呢?下面通过详细地图文,介绍原道M9i的刷机操作过程,在刷机的过程中,要...

如何做好分布式任务调度——Scheduler 的一些探索

作者:张宇轩,章逸,曾丹初识Scheduler找准定位:分布式任务调度平台...

mysqldump备份操作大全及相关参数详解

mysqldump简介mysqldump是用于转储MySQL数据库的实用程序,通常我们用来迁移和备份数据库;它自带的功能参数非常多,文中列举出几乎所有常用的导出操作方法,在文章末尾将所有的参数详细说明...

大厂面试冲刺,Java“实战”问题三连,你碰到了哪个?

推荐学习...

亿级分库分表,如何丝滑扩容、如何双写灰度

以下是基于亿级分库分表丝滑扩容与双写灰度设计方案,结合架构图与核心流程说明:一、总体设计目标...

MYSQL表设计规范(mysql表设计原则)

日常工作总结,不是通用规范一、表设计库名、表名、字段名必须使用小写字母,“_”分割。...

怎么解决MySQL中的Duplicate entry错误?

在使用MySQL数据库时,我们经常会遇到Duplicateentry错误,这是由于插入或更新数据时出现了重复的唯一键值。这种错误可能会导致数据的不一致性和完整性问题。为了解决这个问题,我们可以采取以...

高并发下如何防重?(高并发如何防止重复)

前言最近测试给我提了一个bug,说我之前提供的一个批量复制商品的接口,产生了重复的商品数据。...

性能压测数据告诉你MySQL和MariaDB该怎么选

1.压测环境为了尽可能的客观公正,本次选择同一物理机上的两台虚拟机,一台用作数据库服务器,一台用作运行压测工具mysqlslap,操作系统均为UbuntuServer22.04LTS。...

屠龙之技 --sql注入 不值得浪费超过十天 实战中sqlmap--lv 3通杀全国

MySQL小结发表于2020-09-21分类于知识整理阅读次数:本文字数:67k阅读时长≈1:01...

破防了,谁懂啊家人们:记一次 mysql 问题排查

作者:温粥一、前言谁懂啊家人们,作为一名java开发,原来以为mysql这东西,写写CRUD,不是有手就行吗;你说DDL啊,不就是设计个表结构,搞几个索引吗。...

SpringBoot系列Mybatis之批量插入的几种姿势

...

MySQL 之 Performance Schema(mysql安装及配置超详细教程)

MySQL之PerformanceSchema介绍PerformanceSchema提供了在数据库运行时实时检查MySQL服务器的内部执行情况的方法,通过监视MySQL服务器的事件来实现监视内...

取消回复欢迎 发表评论: