INSERT IGNORE 通过唯一索引捕获 Duplicate entry 错误实现静默跳过,无唯一索引则无效;仅跳过约束冲突,其他错误仍报错;不改变原记录,区别于 REPLACE INTO 的删插逻辑。

INSERT IGNORE 为什么能跳过重复数据
它本质是让 MySQL 在遇到 Duplicate entry 错误时,不报错、不中断、直接跳过当前行。不是“智能判断是否重复”,而是靠唯一索引(UNIQUE 或 PRIMARY KEY)触发的错误捕获机制。
没建唯一索引?INSERT IGNORE 就完全无效,所有数据照插不误,连警告都不会有。
- 必须在目标列上存在
UNIQUE或PRIMARY KEY约束,比如email列加了UNIQUE - 只对违反约束的行静默跳过,其他错误(如字段超长、类型不匹配)仍会报错
- 执行后
mysql_affected_rows()返回值可能为 0(跳过)、1(插入成功)或 -1(出错),不能只看是否 >0 来判断“有没有写入”
INSERT IGNORE 和 REPLACE INTO 的关键区别
REPLACE INTO 不是“忽略”,而是“删+插”:先按唯一索引定位已有行,删掉,再插入新行。如果表有自增主键,会导致 ID 变化;如果有外键关联或触发器,行为更不可控。
INSERT IGNORE 是真·跳过,原记录不动,ID 不变,关联数据不受影响。
- 想保留旧数据、避免主键变动 → 选
INSERT IGNORE - 想用新数据彻底覆盖旧记录(且能接受 ID 重置)→ 才考虑
REPLACE INTO -
INSERT IGNORE不触发ON DUPLICATE KEY UPDATE,别把它和后者混用
实际写法与容易漏掉的细节
语法本身简单,但常因字段顺序、NULL 处理或隐式类型转换导致“看似重复却没跳过”。
比如:INSERT IGNORE INTO users (name, email) VALUES ('Alice', 'alice@example.com');
- 确保
email列有UNIQUE约束,否则这句和普通INSERT没区别 - 注意大小写:如果
email是utf8mb4_unicode_ci排序规则,'Alice@Example.COM'会被视为重复;但如果是utf8mb4_bin,就不重复 -
NULL值在唯一索引中可重复(MySQL 允许多个NULL),所以INSERT IGNORE对NULL不生效 - 批量插入时,只要某一行触发重复,整条语句不会回滚,其余行照常插入
替代方案:ON DUPLICATE KEY UPDATE 更灵活但更重
当你要的不只是“跳过”,而是“已存在就更新某些字段”,ON DUPLICATE KEY UPDATE 是更明确的选择。
例如:INSERT INTO users (id, name, email) VALUES (1, 'Bob', 'bob@example.com') ON DUPLICATE KEY UPDATE name = VALUES(name);
- 它依赖同一套唯一索引机制,但行为可控:冲突时执行指定更新,不冲突就插入
- 性能略低于
INSERT IGNORE(多一次更新逻辑),但语义清晰,适合需要合并逻辑的场景 - 别误写成
INSERT IGNORE ... ON DUPLICATE KEY UPDATE—— 语法冲突,MySQL 直接报错
真正难的从来不是写哪条语句,而是想清楚:重复时,数据状态到底该保持、覆盖,还是部分更新。索引定义、字符集、NULL 处理这些细节,一不留神就让“去重”变成“漏重”或“误重”。










