数据库技巧:INSERT IGNORE的高效插入策略

引用

作为一个软件开发人员,特别是要与数据库打交道的靓仔,你就不可避免的要遇到数据重复插入的问题,如果你没有唯一键或者主键之类的,那无话可说,但是你很好的设计了数据库唯一索引和主键,哪当我们插入数据的时候,你就必须做好去重处理。

代码里面有很多方法,预检查,分布式锁等等;但是有一些场景,我们要快速迁移大量的数据,有的时候会分批次多阶段的处理,这个时候如果都来做预检就很耗时,本文将介绍INSERT IGNORE的用法,特别适合解决这一问题。

一、 基本语法

INSERT IGNORE 是 MySQL 中一个非常实用的语句,用于在插入数据时避免重复键错误(如主键冲突或唯一索引冲突)。它可以帮助你优雅地处理数据重复问题,而不会抛出错误。

INSERT IGNORE 的基本语法与普通的 INSERT 语句非常相似,只是在 INSERT 关键字后面加上了 IGNORE 关键字。以下是常见的语法形式:

  • 插入单行数据
sql 复制代码
INSERT IGNORE INTO table_name (column1, column2, ..., columnN)
VALUES (value1, value2, ..., valueN);
  • 插入多行数据
sql 复制代码
INSERT IGNORE INTO table_name (column1, column2, ..., columnN)
VALUES 
    (value1a, value2a, ..., valueNa),
    (value1b, value2b, ..., valueNb),
    ...
    (value1n, value2n, ..., valueNn);
  • 插入查询结果
sql 复制代码
INSERT IGNORE INTO table_name (column1, column2, ..., columnN)
SELECT column1, column2, ..., columnN
FROM another_table
WHERE condition;

二、 工作原理

INSERT IGNORE 的主要功能是忽略插入操作中可能导致重复键错误的行。以下是其工作原理的详细说明:

2.1 忽略重复键错误

当尝试插入的数据违反了表的唯一性约束(如主键或唯一索引)时,INSERT IGNORE 会自动忽略该插入操作,不会抛出错误。例如:

假设有一个表 users,结构如下:

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:

SQL 复制代码
INSERT IGNORE INTO `user_info`
(`id`, `risk_score`, `risk_level`, `register_time`, `created`, `updated`, `creator`, `updater`) 
VALUES 
('11-000034639cc4408aba88358e73d48517', 10, 0, '2023-02-28 20:28:58', '2025-03-21 17:02:21', '2025-03-21 17:02:36', 'admin', 'admin');

通过下图可以看到,当11-000034639cc4408aba88358e73d48517已经存在的时候,MySQL 会忽略该插入操作,不会报错。

注意:这里只是根据唯一键和主键去判断是否存在,至于其它的值是否发生变化不会拿来判断。

2.2 返回值

INSERT IGNORE 的返回值是一个整数,表示插入操作的结果:

  • 返回值为 1:表示插入成功。

  • 返回值为 0:表示插入操作被忽略(因为数据重复)。

  • 返回值为 n :表示成功插入了 n 行数据(在插入多行时)。

2.3 扩展:查看警告信息

即使 INSERT IGNORE 忽略了插入操作,MySQL 仍然会生成一个警告(Duplicate entry)。你可以通过以下命令查看警告信息:

sql 复制代码
SHOW WARNINGS;

例如:

sql 复制代码
INSERT IGNORE INTO `user_info`(`id`, `risk_score`, `risk_level`, `register_time`, `created`, `updated`, `creator`, `updater`) VALUES ('11-000034639cc4408aba88358e73d48517', 10, 0, '2023-02-28 20:28:58', '2025-03-21 17:02:21', '2025-03-21 17:02:36', 'admin', 'admin');

SHOW WARNINGS;

输出结果如下:

三、 使用场景

INSERT IGNORE 非常适用于以下场景:

3.1 避免重复数据插入

当你需要插入大量数据,但不确定某些数据是否已经存在时,INSERT IGNORE 可以帮助你避免重复插入,同时不会抛出错误。例如:

sql 复制代码
INSERT IGNORE INTO `user_info`(`id`, `risk_score`, `risk_level`, `register_time`, `created`, `updated`, `creator`, `updater`) VALUES 
('11-000034639cc4408aba88358e73d48517', 10, 0, '2023-02-28 20:28:58', '2025-03-21 17:02:21', '2025-03-21 17:02:36', 'admin', 'admin'),
('11-000034639cc4408aba88358e73d48517', 10, 0, '2023-02-28 20:28:58', '2025-03-21 17:02:21', '2025-03-21 17:02:36', 'admin', 'admin');

执行结果:

3.2 数据导入

在从其他数据源导入数据时,INSERT IGNORE 可以确保不会因为重复数据而导致插入失败。例如:

SQL 复制代码
INSERT IGNORE INTO `user_info`(`id`, `risk_score`, `risk_level`, `register_time`, `created`, `updated`, `creator`, `updater`) 
SELECT `id`, `risk_score`, `risk_level`, `register_time`, `created`, `updated`, `creator`, `updater` FROM asrc_user_info;

执行结果:

3.3 日志记录

在记录日志或事件时,INSERT IGNORE 可以确保不会因为重复记录而导致错误。

这种场景主要在于一些日志重复上报的情况。

四、注意事项

虽然 INSERT IGNORE 非常方便,但在使用时还是要慎重,需要注意以下几点:

4.1 不仅限于重复键错误

INSERT IGNORE 不仅会忽略重复键错误,还会忽略其他类型的错误(如外键约束错误)。因此,如果你只想忽略重复键错误,而希望其他错误抛出异常,可以使用 ON DUPLICATE KEY UPDATE 或其他机制。

4.2 性能影响

虽然 INSERT IGNORE 的性能通常较高,但在插入大量数据时,仍然需要注意性能问题。如果表中存在大量唯一索引,可能会导致插入操作变慢。在这种情况下,可以考虑批量插入或优化表结构。

4.3 注意:重要业务数据不能丢

因为是根据唯一键这些进行去重,有一些场景可能是插入或者更新的重要数据,不能使用这个语句,切记。

五、与INSERT插入的区别

看到这里对他们之间的区别相信在脑海中已经有一个概念了,下面我将用一个图更加清晰的表示两者的区别:

从上图可以看出,他们两个实际都是进行了约束检查的,只是一个返回错误信息,停止语句的执行,一个生成告警信息,跳过当前行继续执行。

六、总结

INSERT IGNORE就像一个温柔的数据库管理员,遇到重复数据时不会大喊大叫抛出错误,而是默默跳过,继续处理下一条。

无论是批量导入数据、避免重复插入,还是处理日志重复上报,它都能轻松搞定。

不过,它也有小脾气,比如会忽略所有错误(不只是重复键),所以用的时候得小心。

总之,INSERT IGNORE 是数据库操作中的"温柔一刀",帮你优雅地解决问题,但别忘了检查它的"副作用"哦!

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

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

感谢您的支持和理解!

相关推荐
snowful world4 分钟前
PolyU Palmprint Database掌纹识别数据集预处理(踩坑版)
数据库·人工智能·opencv
YuTaoShao5 分钟前
Java八股文——MySQL「存储引擎篇」
java·开发语言·mysql
白露与泡影8 分钟前
springboot + nacos + k8s 优雅停机
spring boot·后端·kubernetes
Mylvzi22 分钟前
【MySQL 从 0 讲解系列】深入理解 GROUP BY 的本质与应用(含SQL示例+面试题)
数据库·sql·mysql
菜鸟谢26 分钟前
windows xp 下载 sp0 sp1 sp2 sp3 sp4
后端
AirMan28 分钟前
你真的懂 MySQL 的一致性读和当前读的区别吗?
后端·面试
David爱编程34 分钟前
容器性能优化实战指南——防止“吃爆”服务器就靠这些招!
后端·docker·容器
Android洋芋37 分钟前
GitHub项目部署的终极指南:从零到一掌握Docker实战
后端
林太白1 小时前
Next.js超简洁完整篇
前端·后端·react.js
前端付豪1 小时前
汇丰登录风控体系拆解:一次 FaceID 被模拟攻击的调查纪实
前端·后端·架构