insert ignore 能跳过主键/唯一键冲突,因其将冲突视为警告而非错误,仅对已定义主键或唯一索引的重复键生效,其他约束错误仍会报错中止。

INSERT IGNORE 为什么能跳过主键/唯一键冲突?
INSERT IGNORE 的本质是把冲突当作警告(warning)而非错误(error),让语句继续执行而不是中断整个批量操作。它只对违反 PRIMARY KEY 或 UNIQUE 约束的行生效,其他错误(比如字段类型不匹配、NOT NULL 字段插入 NULL)依然会报错中止。
- 只有表上明确定义了主键或唯一索引时,
INSERT IGNORE才起作用 - MySQL 5.7+ 默认开启
sql_mode=STRICT_TRANS_TABLES,但IGNORE会绕过严格模式对重复键的拦截 - 执行后可通过
SELECT ROW_COUNT()查看实际插入了几行(返回值为 0 表示全被忽略)
INSERT IGNORE 和 REPLACE INTO、ON DUPLICATE KEY UPDATE 有什么区别?
三者都处理写入冲突,但行为完全不同:
-
INSERT IGNORE:冲突就跳过,不修改已有数据,也不影响自增 ID -
REPLACE INTO:先 DELETE 再 INSERT,会触发删除和插入两个事件,自增 ID 可能递增,外键关联可能被破坏 -
ON DUPLICATE KEY UPDATE:冲突时执行指定更新,适合“存在则更新,不存在则插入”场景,但语法稍长
如果只是想“确保不报错、不重复插入”,INSERT IGNORE 最轻量;如果后续要更新时间戳或计数器,就得换用 ON DUPLICATE KEY UPDATE。
批量插入时 INSERT IGNORE 的实际写法和常见坑
写法本身很简单:在 INSERT 前加 IGNORE 关键字,后面跟标准的 VALUES 或 SELECT。
INSERT IGNORE INTO users (id, name, email) VALUES (1, 'Alice', 'a@example.com'), (2, 'Bob', 'b@example.com'), (3, 'Charlie', 'c@example.com');
容易踩的坑:
- 没建唯一索引却以为能去重:必须确认
email字段上有UNIQUE索引,否则IGNORE完全无效 - 混用
INSERT IGNORE和事务:它不会回滚已成功插入的行,只跳过冲突行;如果前面几行成功、中间一行冲突、后面又成功,最终结果是部分写入 - 误以为能忽略所有错误:遇到
Column 'xxx' cannot be null这类约束错误,语句仍会失败,IGNORE不起作用
如何验证 INSERT IGNORE 是否按预期工作?
别只看“没报错”就认为成功了。应主动检查:
- 执行后运行
SELECT ROW_COUNT():返回值是本次真正新增的行数(不是总行数) - 查询目标表,确认重复数据没被覆盖、也没多出异常记录
- 开启通用日志或慢查询日志时,注意
INSERT IGNORE的冲突会记为 warning,不是 error,日志里可能被忽略
真正难的是设计阶段——得提前想清楚:哪些字段组合必须唯一?是否允许部分失败?要不要事后统计被忽略的条目?这些决定了你该用 INSERT IGNORE,还是换更可控的方式如应用层预查 + 单条事务插入。










