insert ignore仅精准跳过primary key或unique约束冲突,将error 1062转为warning并继续执行;其他错误(如not null违反、类型不匹配)仍报错,且必须存在对应唯一索引才生效,否则行为等同普通insert。

MySQL 用 INSERT IGNORE 跳过主键冲突
它只对 PRIMARY KEY 或 UNIQUE 约束冲突静默处理,其他错误(如 NOT NULL 违反、类型不匹配)照常报错。不是“兜底容错”,而是精准跳过重复插入。
- 必须确保目标列有明确的
PRIMARY KEY或UNIQUE索引,否则行为和普通INSERT完全一致 - 执行后
mysql_affected_rows()返回0表示被忽略,不是失败——别拿这个当异常判断依据 - 批量插入时效率高,但单次建议不超过 1000 行,避免长事务锁表
- 多个唯一索引(比如
email和phone都设了UNIQUE),只要任一冲突,整行就被丢弃,不会部分插入 -
NULL值在唯一索引中通常不视为重复(标准 SQL 行为),所以多条INSERT IGNORE插入email = NULL可能成功多次,逻辑上却算“重复”
需要更新已有数据?改用 ON DUPLICATE KEY UPDATE
当你不只是想“跳过”,还想顺手更新时间戳、计数器或业务字段时,INSERT IGNORE 就不够用了。
- 语法形如:
INSERT INTO users (id, name, updated_at) VALUES (123, 'Alice', NOW()) ON DUPLICATE KEY UPDATE name = VALUES(name), updated_at = NOW(); -
VALUES(col)引用的是本次INSERT中该列的值,不是当前行原值 - 只响应第一个触发的唯一键冲突(MySQL 按索引定义顺序检查),若表有多个唯一约束,需确认业务逻辑覆盖全部可能路径
- 性能略低于
INSERT IGNORE,因为要额外执行UPDATE,但在幂等写入场景下语义更清晰、更少误用
SQL Server 怎么办:靠 IGNORE_DUP_KEY 表级设置
SQL Server 不支持 INSERT IGNORE 语法,也不能在单条语句里加 IGNORE 关键字。它的方案是提前在索引上启用 IGNORE_DUP_KEY = ON。
- 必须在建表或修改索引时显式开启:
CREATE UNIQUE INDEX uk_email ON users(email) WITH (IGNORE_DUP_KEY = ON); - 一旦开启,所有对该索引的
INSERT操作都会自动跳过冲突行,无需改 SQL - 注意:这是表/索引级别的全局开关,不是语句级控制;且仅对
UNIQUE索引生效,主键默认不允许设IGNORE_DUP_KEY - 如果没权限改索引结构,只能退回到应用层先查后插(需配
@Transactional防并发)或用MERGE语句
真正容易被忽略的点
很多人花时间调语法,却栽在设计上:唯一性约束没对准业务本质。比如只给 email 加 UNIQUE,但实际业务要求 “手机号 + 渠道码” 组合才唯一;或者把空字符串 '' 和 NULL 当成等价去判断,而数据库里它们是不同值,约束行为也不同。写之前先问一句:什么才算一条重复记录?答案不在代码里,在业务规则里。











