下面我用 最清晰、最实战、最容易理解 的方式,彻底讲清:
✅ 1. INSERT IGNORE
忽略冲突,不会报错,也不会更新已有数据
📌 场景
当插入数据时,如果遇到 唯一索引 / 主键冲突 ,MySQL 会自动忽略该行,不报错,不更新。
📌 示例
insert ignore into user(id, username)
values (1, 'zhang');
📌 结果
- 若 id=1 不存在 → 正常插入
- 若 id=1 已存在 → 这条语句 什么都不做(不报错、不更新)
✔ 适用场景
- 你只想插入不存在的记录
- 不想更新旧数据
- 不想让系统因为冲突而报错
✅ 2. REPLACE INTO
先删除旧数据,再插入新数据(会触发删除 + 插入)
📌 行为如下:
- 检查主键/唯一索引是否冲突
- 若冲突 → ❗先 DELETE 删除旧行
- 再 INSERT 新行
📌 示例
replace into user(id, username)
values (1, 'newName');
📌 结果
-
若 id=1 不存在 → 直接插入
-
若 id=1 已存在 →
- 旧数据被删除
- 插入新的数据
⚠ 必须注意
- 会触发 删除触发器、插入触发器
- 会导致自增 id 变化
- 会导致其他外键可能出问题
- 性能比
insert ignore和on duplicate key update差
✔ 适用场景
你确定冲突时应该 整个覆盖 数据,而不是修改一部分字段。
✅ 3. ON DUPLICATE KEY UPDATE
主键/唯一索引冲突时执行 UPDATE,不冲突时执行 INSERT
📌 行为
- 若没有冲突 → INSERT
- 若有冲突 → 执行 UPDATE(不会删除旧数据)
📌 示例
insert into user(id, username, age)
values (1, 'zhang', 18)
on duplicate key update
username = values(username),
age = values(age);
📌 结果
- 若 id=1 不存在 → 插入
- 若 id=1 已存在 → 更新 username, age
✔ 适用场景
平时最常用:
- 插入新数据
- 若存在,则更新部分字段(例如更新时间、数量累加等)
🔥 三者对比总结(牢记)
| 语句 | 无冲突 | 有冲突(主键/唯一) | 是否删除旧数据 | 是否更新旧数据 |
|---|---|---|---|---|
| insert ignore | 插入 | 忽略,不报错 | ❌ 不删除 | ❌ 不更新 |
| replace into | 插入 | 先删旧,再插入新 | ✔ 删除 | ✔ 覆盖(插入新行) |
| on duplicate key update | 插入 | 更新已有数据 | ❌ 不删除 | ✔ 更新 |
🔥 哪个最好?
| 场景 | 推荐语句 |
|---|---|
| 只想插不存在的 | insert ignore |
| 若存在就更新部分字段 | on duplicate key update ⭐最常用 |
| 完全覆盖旧数据(适合整行替换) | replace into |
💡 实战示例(你会经常用到)
1️⃣ 插入没问题、冲突直接略过
insert ignore into user(id, name) values (1, 'a');
2️⃣ 插入或更新
insert into user(id, score)
values (1, 10)
on duplicate key update score = score + 10;
3️⃣ 完全替换一条记录
replace into user(id, name, age)
values (1, 'newName', 20);