INSERT IGNORE仅在MySQL中对PRIMARY KEY或UNIQUE约束冲突静默跳过,其他数据库需用各自语法;没建唯一索引是跳过失效的最常见原因,且NULL值不触发判重。

INSERT IGNORE 只在 MySQL 中有效,且仅对 PRIMARY KEY 或 UNIQUE 约束冲突静默跳过;其他数据库需用各自语法,硬套会报错。
MySQL 里 INSERT IGNORE 为什么没跳过重复?
最常见原因是目标字段压根没建唯一约束。MySQL 不比对数据内容,只靠索引触发冲突检测。
- 执行
SHOW CREATE TABLE your_table;,确认输出里有类似UNIQUE KEY `uniq_email` (`email`)的定义 - 若缺失,补加索引:
ALTER TABLE users ADD UNIQUE KEY uniq_email (email);(注意:已有重复值会导致建索引失败) - 复合唯一索引也行,比如
(user_id, event_type),适合组合判重场景 -
INSERT IGNORE对NULL值不判重——多个email = NULL的记录能同时插入,即使字段有UNIQUE索引
PostgreSQL 怎么等效实现“跳过”?
PostgreSQL 没有 IGNORE 关键字,必须用 ON CONFLICT DO NOTHING,且必须显式指定冲突列或约束名。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 基础写法:
INSERT INTO users (id, email) VALUES (1,'a@b.com') ON CONFLICT (email) DO NOTHING; - 更安全的写法(避免列名歧义):
ON CONFLICT ON CONSTRAINT idx_users_email DO NOTHING; - 不能省略
DO NOTHING,否则语法错误;也不能写成DO UPDATE SET,那就不叫“跳过”了 - 如果表有多个唯一索引,只响应你明确写出的那个冲突路径,不会自动覆盖其他索引
SQL Server 和 SQLite 怎么办?
SQL Server 不支持语句级忽略,得靠索引级配置;SQLite 则提供最简语法,但能力有限。
- SQL Server 必须提前启用
IGNORE_DUP_KEY = ON:CREATE UNIQUE INDEX uk_email ON users(email) WITH (IGNORE_DUP_KEY = ON);—— 这是全局开关,不是单条语句控制 - SQLite 用
INSERT OR IGNORE,语法最接近 MySQL:INSERT OR IGNORE INTO users (id, name) VALUES (1, 'Alice'); - SQLite 的
OR IGNORE不返回任何提示,也不影响last_insert_rowid(),事务中它仍算一次执行 - 三者都不处理非唯一性错误:字段超长、
NOT NULL违例、类型不匹配……这些照样报错中断
别踩这些隐性坑
真正难的不是写对语法,而是理解它“跳过”的边界在哪里。
-
INSERT IGNORE返回affected_rows = 0表示被忽略,不是失败;别拿这个当异常信号 - 批量插入时,只要有一行因字段超长报错,整条语句就中断——
IGNORE只管唯一冲突,不管其他 - 事务中使用,已成功插入的行不会回滚,被忽略的行也不触发回滚,需自行控制事务粒度
- ORM(如 SQLAlchemy)建议优先用
upsert方法,避免底层驱动对IGNORE解析不一致

















