问:现在我的业务中有这样的需求:如果目标记录存在的话我就更新它,如果记录不存在的话我就插入。说说看你知道哪些实现方式吧!
1. 判断逻辑:先查询,再更新/插入,会和Mysql发生2次网络交互。
// 伪代码user=User.FindById(1)if user == null{user.Insert()}else{user.Update()}
缺点:
- 会和Mysql发生2次网络交互;
- 并发访问场景下,会有并发修改异常。
2.影响行数:先尝试更新,没有记录则影响行数为0,再插入,和Mysql的网络交互可能降低成1。
// 伪代码
effectRows=User.UpdateById(1)
if effectRows >0 {
user.Insert()
}
缺点:
- update实例的信息与数据库中记录完全一致,update影响的行数为0,则执行insert语句,会报错主键冲突。
3.insert ignore into:如果记录存在了就ignore本次插入,如果记录不存在就写入。判断是否可以写入的标准是:唯一键不能重复。
insert ignore into table_name(id, name) values(1, 'jerry');
缺点:
- insert ignore into 并不能满足我们的业务需求。只要你想写入的数据和现有的唯一键冲突了,最终就不会将你的数据落库。
4.replace into:如果记录存在了就更新,如果记录不存在就写入。
判断数据是否已经存在的标准依然是:唯一键是否重复。
而且这个替换还是全量替换:
replace into table_name(id, name) values(1, 'jerry');
5.on duplicate key update:如果记录存在(判断标准是主键)了就更新,如果记录不存在就写入。
insert into table_name(id, name) values(1, 'jerry') on duplicate key update name = 'tom';
缺点:
- 多个唯一主键的时候,要避免使用;
- 使用on duplicate key update即使实际执行的是update,也会调用LAST_INSERT_ID()函数,导致自增的主键id出现不再是递增的幻觉,而是跳着增长的。

