必须先建唯一索引,否则所有“跳过重复”语法均无效;mysql用insert ignore(仅对unique/primary key冲突静默跳过)、postgresql用on conflict do nothing(须明确冲突列)、sql server依赖merge语句、sqlite用insert or ignore,均需对应唯一约束支持。

必须先建唯一索引,否则所有“跳过重复”的语法都无效。
MySQL 用 INSERT IGNORE 最快但最不精确
它只对 UNIQUE 或 PRIMARY KEY 冲突静默跳过,其他错误(如字段超长、NOT NULL 插入 NULL)仍会报错并中断整条语句。
- 必须确保目标列已加
UNIQUE索引,例如:ALTER TABLE users ADD UNIQUE (email); -
INSERT IGNORE INTO users (email, name) VALUES ('a@b.com','Alice'), ('a@b.com','Bob');—— 第二行被跳过,不报错 - 返回的
affected rows数量会少于 VALUES 行数,差值即为跳过数 - 大小写敏感性取决于排序规则:
utf8mb4_unicode_ci下A@B.COM和a@b.com被视为重复;utf8mb4_bin则不重复 -
NULL在唯一索引中可重复,所以含NULL的行不会触发跳过逻辑
PostgreSQL 必须用 ON CONFLICT DO NOTHING 显式指定冲突列
不能省略 DO NOTHING,也不能只写 ON CONFLICT —— 语法直接报错。
- 冲突目标必须明确:写成
ON CONFLICT (email)或更安全的ON CONFLICT ON CONSTRAINT idx_users_email - 如果表主键是复合的(如
(name, gender, age)),必须写全:ON CONFLICT (name, gender, age) DO NOTHING INSERT INTO users (email, name) VALUES ('x@y.com','X') ON CONFLICT (email) DO NOTHING;- 不支持
IGNORE关键字;用错写法(比如漏掉DO NOTHING)会直接抛出syntax error
SQL Server 没有原生跳过语法,MERGE 是事实标准
它不是 INSERT 的变体,而是独立语句,漏写 WHEN NOT MATCHED 就等于没写插入逻辑。
- 必须搭配
USING提供源数据,常用VALUES构造:MERGE users AS t USING (VALUES (1,'A'),(2,'B')) AS s(id,name) ON t.id = s.id WHEN NOT MATCHED THEN INSERT (id,name) VALUES (s.id,s.name); - 目标表
users必须有唯一索引(如id主键),否则ON条件无法保证匹配唯一性 - 初学者常误以为
MERGE默认跳过,结果整条语句无效果,或意外触发WHEN MATCHED分支导致更新 - 高并发下若用
IF NOT EXISTS+ 事务替代,必须配SERIALIZABLE隔离级和UPDLOCK,否则仍有竞态
SQLite 用 INSERT OR IGNORE,注意它和 MySQL 的 IGNORE 行为一致
语法最接近 MySQL,但关键字是 OR IGNORE,不是 IGNORE 单独出现。
-
INSERT OR IGNORE INTO users (email, name) VALUES (?, ?);配合executemany()批量执行效率最高 - 同样依赖
UNIQUE约束生效;没建索引时该语句等价于普通INSERT - Python 中不要在循环里单条执行
INSERT OR IGNORE,性能差一个数量级 - 返回的
rowcount可能为 0(跳过)、正数(成功插入行数),但不会因非约束错误而中断
真正容易被忽略的是:所有这些机制只保障单条 SQL 语句原子性。如果你要插入订单同时扣减库存,光靠 INSERT OR IGNORE 无法保证跨表一致性 —— 那得靠事务 + 锁,或者业务层幂等设计。










