INSERT IGNORE仅对主键或唯一索引冲突(ER_DUP_ENTRY/1062)生效,将其降级为警告并跳过该行;其他错误(如NULL插入NOT NULL字段、字符串超长)仍报错中断,且必须有实际生效的PRIMARY KEY或UNIQUE索引才起作用。

INSERT IGNORE 只对主键或唯一索引冲突生效,其他错误(比如 NULL 插入 NOT NULL 字段、字符串超长)依然会报错中断——它不是“静默兜底”,而是“精准忽略”。
什么时候 INSERT IGNORE 真正跳过一行?
只有当 MySQL 内部抛出 ER_DUP_ENTRY(错误码 1062)时,INSERT IGNORE 才会把那行转为警告并跳过。其余任何错误都照常中断。
- 表必须有实际生效的
PRIMARY KEY或UNIQUE索引——仅声明UNIQUE约束但没建索引?INSERT IGNORE不起作用 - 联合唯一索引(如
UNIQUE KEY (a,b))要求所有列值完全匹配才触发跳过;只提供a值,不会跳 - 批量插入中,某行因重复被跳过,其余合法行仍会插入;返回的
affected_rows是成功行数,不是总行数 - 执行后务必查
SHOW WARNINGS,看到Warning | 1062 | Duplicate entry才确认真跳过了
INSERT IGNORE 返回值怎么解读?
mysql_affected_rows()(C API)、cursor.rowcount(PyMySQL)或 result.affectedRows(Node.js mysql2)返回的是「实际插入的新行数」,不是「处理了多少行」。
- 返回
0:可能整条语句全跳过,也可能全失败(比如字段超长),需结合SHOW WARNINGS判断 - 返回
1:正常插入了一行 - 返回
2:批量插入中两行都成功,没触发任何跳过 - 返回
1但SHOW WARNINGS里有1062:说明批量中有一行被跳过、另一行成功了
为什么不能用 INSERT IGNORE 替代 ON DUPLICATE KEY UPDATE?
语义完全不同:一个是「丢弃」,一个是「更新」。业务意图错位时,数据会静默丢失。
-
INSERT IGNORE INTO users (email, name) VALUES ('a@b.com', 'NewName'):如果email已存在,整行丢弃,旧name保留 -
INSERT INTO users (email, name) VALUES ('a@b.com', 'NewName') ON DUPLICATE KEY UPDATE name = VALUES(name):冲突时只改name,其他字段不变 -
INSERT IGNORE在事务中不提供回滚粒度——哪怕只有一行冲突被跳过,前面已成功的行也已提交 - 想记录哪几行被跳过?
INSERT IGNORE不提供明细,得靠SELECT ... WHERE NOT EXISTS+ 显式循环,但有竞态风险
UPDATE IGNORE 和 DELETE IGNORE 实际管什么?
它们的作用范围和常见误解差距很大,别凭名字瞎猜。
-
UPDATE IGNORE:只在更新目标行时因唯一键冲突(比如设了个已被别人占用的email)才跳过该行更新;其他错误(类型转换失败、字段越界)仍报错 -
DELETE IGNORE:几乎只在外键场景下有意义——父记录被子表引用且没设ON DELETE CASCADE时,普通DELETE报错,加IGNORE后发警告但不停止;对无外键的表,它和普通DELETE行为一致 - 三者都不改变事务原子性:一条语句里部分成功,就真成功了,没法单独回滚被跳过的那几行
Query OK, 0 rows affected,第一反应是“没插进去”,但可能是全跳过,也可能是全失败——不看 SHOW WARNINGS,永远不知道 MySQL 到底干了什么。


















