INSERT IGNORE 仅忽略违反 PRIMARY KEY 或 UNIQUE 约束的重复键错误,如主键或唯一索引值已存在;对 FOREIGN KEY 冲突、数据截断、无效日期等其他错误均不忽略。

MySQL 的 INSERT IGNORE 不是万能的“跳过所有错误”,它只对重复键(Duplicate entry)和部分 NULL 插入主键/唯一键约束失败生效,其他错误(如数据截断、类型不匹配、外键冲突)仍会报错并中断语句。
哪些错误会被 INSERT IGNORE 真正忽略?
仅当违反 PRIMARY KEY 或 UNIQUE 约束时,INSERT IGNORE 才静默跳过该行。典型触发场景包括:
- 插入已存在的主键值(如
id = 5已存在,再插INSERT IGNORE INTO t VALUES (5, 'a')) - 插入已存在的唯一索引值(如邮箱字段加了
UNIQUE,重复邮箱被忽略) - 向定义为
NOT NULL且无默认值的列插入NULL(仅当该列同时是主键或唯一键的一部分时才被忽略;否则报错)
注意:INSERT IGNORE 对 FOREIGN KEY 违反、DATA TRUNCATION(如字符串超长)、INVALID DATE 等一律不忽略,仍抛出警告或错误。
INSERT IGNORE 和 ON DUPLICATE KEY UPDATE 的关键区别
两者都处理重复键,但行为逻辑完全不同:
-
INSERT IGNORE:遇到重复键,整行丢弃,不报错,不修改任何已有数据 -
ON DUPLICATE KEY UPDATE:遇到重复键,执行后面的更新逻辑(如INSERT INTO t VALUES (1,'x') ON DUPLICATE KEY UPDATE name='y') - 性能上,
IGNORE开销略小,因为它不做后续更新;但若你本意是“有则更新”,用IGNORE会导致数据陈旧 - 返回值也不同:
INSERT IGNORE成功插入 N 行、忽略 M 行时,mysql_affected_rows()返回 N;而ON DUPLICATE KEY UPDATE更新一行也会算作“1 行受影响”
容易踩的坑:NULL 值 + 唯一键组合的陷阱
当唯一索引包含可为 NULL 的列时,INSERT IGNORE 的行为容易误判。例如:
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
CREATE TABLE t (a INT, b INT, UNIQUE(a,b));
此时插入 INSERT IGNORE INTO t VALUES (1, NULL) 和 INSERT IGNORE INTO t VALUES (1, NULL) —— MySQL 认为两个 NULL 不相等,因此**不会触发忽略**,第二条会成功插入!这导致“看似重复却没被跳过”。
解决办法只有两个:
- 避免在唯一索引中使用可空列;或
- 改用生成列(generated column)+ 唯一索引,把
NULL显式转为某个确定值(如COALESCE(b, -1))
替代方案:什么时候不该用 INSERT IGNORE?
如果你需要更精细的控制,比如只忽略某类错误、记录哪些行被跳过、或兼容严格 SQL 模式,INSERT IGNORE 就不够用了:
- 在严格模式(
STRICT_TRANS_TABLES)下,某些本该警告的截断会被升级为错误,IGNORE依然无效 - 想区分“跳过”和“真正插入”,得依赖客户端检查
affected_rows,而不是靠错误码 - 批量插入时混合了多种错误类型,建议先用
SELECT ... WHERE NOT EXISTS预检,或改用应用层去重
真正难处理的从来不是“怎么跳过”,而是“跳过之后,你怎么确认跳得合理、没掩盖数据问题”。INSERT IGNORE 是个快捷键,不是纠错机制。










