使用唯一索引约束防止重复数据。需要注意的是创建唯一索引的字段若存在NULL值,唯一约束对于NULL值会失效(但不影响其他非NULL值的记录间的唯一约束),因此尽量将唯一约束和非空约束组合使用
逻辑删除场景下的唯一约束
一般我们会在表中使用
is_deleted
字段表示删除状态。如果只在唯一字段上加唯一约束,当该条记录逻辑删除后,再添加一条同名的数据仍会报错,因为逻辑上删除的数据在数据库中真实存在,只不过is_deleted
字段的值表示已删除罢了
1. 在(唯一字段+is_deleted
)建立联合唯一约束
假如只使用0和1代表删除状态,新增数据时没有问题, 但是删除会存在问题,如下,第二次删除时会报错
name | is_deleted | |
---|---|---|
第一次(新增后删除) | aaaa | 1 |
第二次(再次新增后删除) | aaaa | 1 |
该问题的原因是仅用一个值表示删除的状态,在逻辑删除时自然会因为重复而报错
a. 我们可以使用多个不重复的值来表示已删除状态。例如使用0
表示未删除状态,1、2、3、4...
来表示已删除状态,也可参照主键的值来设置对应删除状态的值(因为主键本身不可能重复)
update category set is_deleted = id + 1 where id = #{id};
--- id + 1 是为了防止id从0开始自增,若id从1开始,可不用 + 1而直接使用id值作为对应记录的删除状态的值
使用mybatis-plus框架,设置如下(未验证)
b. 还有种思想是依然使用0
表示未删除状态,并将其作为默认值,使用NULL值表示已删除状态。由于NULL值会导致唯一约束失效,刚好可以在删除时不会因为唯一约束而失败。
- 若使用的mybatis-plus版本不支持通过上述配置的方式将删除状态的值设置为NULL,则需要自定义BaseMapper进行扩展
2. 增加字段delete_id
如果不想更改
is_deleted
原有的字段逻辑(只使用两个值0
和1
或true
和false
表示)可增加一个字段,专门用于和唯一字段组合成唯一约束,默认值设置为
0
, 即新增数据时该字段值为0
,逻辑删除时将该字段更新为对应主键的值