INSERT IGNORE仅在触发ERROR 1062重复键冲突时静默跳过并转为警告,继续执行后续插入;对字段超长、NULL插入NOT NULL列等其他错误仍报错中断,且必须有PRIMARY KEY或UNIQUE索引才生效。

INSERT INTO 遇到主键或唯一索引冲突会直接报错并中断执行;INSERT IGNORE 会把这类冲突当作警告跳过,继续插入后续合法行——这是最核心的区别,不是“更温柔”,而是行为逻辑完全不同。
INSERT IGNORE 什么时候会静默跳过?
只有当冲突触发的是 ERROR 1062 Duplicate entry 类错误时,INSERT IGNORE 才生效。它不处理外键约束失败、字段长度超限、NULL 插入非空列等其他错误,这些仍会报错中断。
常见误判场景:
- 表没定义
PRIMARY KEY或UNIQUE索引 →INSERT IGNORE和INSERT INTO行为完全一样,不会跳过任何行 - 用
INSERT IGNORE插入含非法日期(如'0000-00-00')的记录 → 依然报错,和 ignore 无关 - 事务中混合使用
INSERT IGNORE和普通INSERT INTO→ 前者跳过、后者报错,事务可能部分提交,需手动控制
INSERT IGNORE 的返回值怎么看?
INSERT INTO 返回实际插入的行数(比如批量插 10 行全成功,返回 10);INSERT IGNORE 返回的是「真正新增的行数」,跳过的重复行不计入。
例如执行:
INSERT IGNORE INTO users (id, name) VALUES (1,'a'),(1,'b'),(2,'c');若 id=1 已存在,则只插入 id=2 这一行,返回值是
1,不是 3 或 2。
注意:mysql_affected_rows() 或 mysqli->affected_rows 拿到的就是这个数,别误以为是“尝试总数”。
为什么有时候 INSERT IGNORE 看似没效果?
根本原因往往是:你以为有重复,其实没有;或者你以为跳过了,其实压根没触发唯一约束。
排查建议:
- 确认目标列确实建了
UNIQUE或PRIMARY KEY,用SHOW CREATE TABLE table_name看真实 DDL - 检查数据是否真重复:比如字符串尾部空格、大小写(
utf8mb4_general_ci不区分大小写)、隐式类型转换('1'vs1)都可能导致“看似重复实则不同” - 查 warning:执行后立刻运行
SHOW WARNINGS,能看到被忽略的具体原因,比如Level: Warning, Code: 1062, Message: Duplicate entry 'xxx' for key 'PRIMARY'
INSERT IGNORE 不是万能去重方案
它只解决“不想报错+不想覆盖”的简单场景。如果需要更新已有记录字段,得用 INSERT ... ON DUPLICATE KEY UPDATE;如果要强制替换整行(包括清空未指定字段),才考虑 REPLACE INTO。
容易被忽略的一点:INSERT IGNORE 跳过行为不可逆,也不留日志痕迹——出问题时你只能靠 warning 或应用层日志追溯,数据库本身不记录“哪些行被忽略了”。


















