在创建数据库表的时候,我们可能会对表中的除主键id外的其它单个字段建立唯一索引UNIQUE INDEX
,或者是多个字段组合起来的唯一联合索引(比如‘id, uid, brandId, …’,其中id是主键索引,uid_brandId建立唯一联合索引,brandId建立唯一索引)。
当执行insert
操作对表中插入数据时,如果跟表中已存在的唯一索引的数据冲突,则该操作会执行失败,怎么避免这种情况发生呢?正确做法应该是如果发生冲突则不做插入操作转而做更新操作,以下列举两种方法:
- 先做查询判断,再做操作
因为唯一索引在表中肯定是唯一存在的,在做insert
插入时,可以先拿插入参数中的唯一索引字段(如上文提到的‘uid’)去表中查询,如果返回值为空则代表没有冲突,可以进行insert
操作,反之则冲突,则走update
操作。
if (Objects.isNull(getInfoByUid(param.getUid()))){
//添加操作
addC(param);
}
else {
//如果该uid存在,则更新
update(param);
}
2.在sql中使用
ON DUPLICATE KEY UPDATE
在 insert into 语句后面添加 ON DUPLICATE KEY UPDATE,该条sql就会自动判断插入的数据是否和已存在的唯一索引发生冲突,如果没有冲突则执行insert操作,如果发生冲突则不会执行insert而是执行后面的update操作。
条件 | 操作 |
---|---|
唯一索引/主键相同 | 更新原有数据 |
唯一索引/主键不同 | 插入新数据 |
实例如下:
<insert id="xxx" >
insert into table(`uid`,`brandId`,`status`,`createTime`,`updateTime`)
values (#{uid},#{brandId},'0',sysDate(),sysDate())
ON DUPLICATE KEY UPDATE brandId = VALUES(brandId), createTime = VALUES(createTime), status = 0, updateTime = VALUES(updateTime)
</insert>
两种方法的优先使用场景和优缺点:
方法一会对数据库多做一次查询操作,在时间上会相对于方法二多消耗一点;
方法二如果插入的字段比较多的情况下,整条sql语句会显得非常冗长;
总结:如果插入的字段比较多并且对时间效率要求不是特别高的话,使用方法一,反之则使用方法二。
再说几句:
1:ON DUPLICATE KEY UPDATE需要在INSERT语句中存在主键或者唯一索引的列,并且对应的数据已经在表中才会执行更新操作。而且如果要更新的字段是主键或者唯一索引,不能和表中已有的数据重复,否则插入更新都失败。
2:不管是更新还是增加语句都不允许将主键或者唯一索引的对应字段的数据变成表中已经存在的数据。