引用
作为一个软件开发人员,特别是要与数据库打交道的靓仔,你就不可避免的要遇到数据重复插入的问题,如果你没有唯一键或者主键之类的,那无话可说,但是你很好的设计了数据库唯一索引和主键,哪当我们插入数据的时候,你就必须做好去重处理。
代码里面有很多方法,预检查,分布式锁等等;但是有一些场景,我们要快速迁移大量的数据,有的时候会分批次多阶段的处理,这个时候如果都来做预检就很耗时,本文将介绍
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
是数据库操作中的"温柔一刀",帮你优雅地解决问题,但别忘了检查它的"副作用"哦!
希望本文对您有所帮助。如果有任何错误或建议,请随时指正和提出。
同时,如果您觉得这篇文章有价值,请考虑点赞和收藏。这将激励我进一步改进和创作更多有用的内容。
感谢您的支持和理解!