IntegrityError主键冲突是MySQL发出的信号而非程序崩溃,因它明确告知重复插入;应根据业务意图选择INSERT IGNORE、ON DUPLICATE KEY UPDATE或慎用REPLACE INTO,并始终在事务中使用原子语句避免竞态。

为什么 IntegrityError 主键冲突不是“报错”,而是“信号”?
它不是程序崩了,是 MySQL 明确告诉你:INSERT 的那条记录,主键(或唯一索引)值已经存在。Python 的 mysql-connector-python 或 pymysql 只是把这条 SQL 错误原样抛出来,错误信息里通常含 1062 Duplicate entry 和具体字段名。
关键判断:你是否**本意就是避免重复插入**?如果是,就别急着 try-except 吞掉错误,而该用更稳妥的写法。
用 INSERT IGNORE 快速跳过重复项
适用于:批量导入数据、日志去重、不关心是否插入成功,只要不中断流程。
-
INSERT IGNORE INTO users (id, name) VALUES (123, 'Alice')—— 如果id=123已存在,语句静默跳过,cursor.rowcount返回 0 - 注意:它会忽略所有违反约束的错误(不仅是主键,还包括唯一键、非空等),可能掩盖其他问题
- MySQL 8.0+ 支持,但
mysql-connector-python和pymysql都兼容
用 ON DUPLICATE KEY UPDATE 实现“有则更新,无则插入”
适用于:用户资料同步、计数器累加、状态刷新等需要合并逻辑的场景。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
INSERT INTO users (id, name, updated_at) VALUES (123, 'Alice', NOW()) ON DUPLICATE KEY UPDATE name=VALUES(name), updated_at=NOW()-
VALUES(col)引用的是本次 INSERT 中对应列的值,不是当前行旧值 - 主键或唯一索引冲突才会触发 UPDATE;如果表没定义任何唯一约束,这句退化为普通 INSERT
- 执行后
cursor.rowcount返回 1(新插入)或 2(更新触发),可据此判断行为
用 REPLACE INTO 要小心主键自增和外键级联
它本质是「删 + 插」:先按主键/唯一键 DELETE 匹配行,再 INSERT 新行。
-
REPLACE INTO users (id, name) VALUES (123, 'Alice')—— 若存在 id=123 的行,会先删后插 - 自增主键会递增(哪怕只是 REPLACE 同一个 ID),可能导致 ID 浪费
- 若该行被其他表外键引用且定义了
ON DELETE CASCADE,REPLACE 会触发级联删除,这是隐式副作用 - 性能比
INSERT ... ON DUPLICATE KEY UPDATE差,尤其在大表或有触发器时
真正容易被忽略的点:事务边界。无论用哪种方案,都得确保操作在同一个事务里完成——比如先 SELECT 再 INSERT 的“检查后插入”模式,在并发下必然产生竞态条件,IntegrityError 依然会发生。所以别手写 if not exists SELECT...,直接交给 MySQL 的原子语句处理。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










