处理数据库中的逻辑删除(即不真正删除记录,而是标记其为已删除)与唯一性约束之间的冲突

原始需求
假设我们有一个用户表 t_user,其中用户名 user_name 是唯一的。为了保持数据的历史记录,我们不希望直接删除用户的记录,而是通过设置一个 is_delete 标记来表示用户记录是否已被删除

初始方案
初始方案中,我们在 user_name 上设置了唯一索引,并且增加了 is_delete 字段。然而,当我们尝试在逻辑删除一个用户之后再插入一个具有相同用户名的新用户时,由于唯一性约束的存在,新的插入操作会失败。

改进方案
为了绕过这个问题,我们可以采用以下方法:

增加 delete_time 字段:用于记录逻辑删除发生的时间。
使用组合唯一索引在 user_name 和 delete_time 上设置唯一索引
这样做的目的是为了让相同的 user_name 在不同的 delete_time 下可以共存。当一个用户被逻辑删除后,其 delete_time 不为零,而新插入的用户将拥有 delete_time 为零的记录,从而避免唯一性冲突。

SQL 示例
让我们用具体的 SQL 语句来演示这一过程:

创建表Sql

CREATE TABLE IF NOT EXISTS `t_user` (
    `id` VARCHAR(32) NOT NULL PRIMARY KEY COMMENT '用户id',
    `user_name` VARCHAR(64) NOT NULL COMMENT '用户名,唯一',
    `is_delete` SMALLINT NOT NULL DEFAULT 0 COMMENT '逻辑删除标记,0:否,1:是',
    `delete_time` BIGINT NOT NULL DEFAULT 0 COMMENT '逻辑删除时间,默认为0',
    UNIQUE KEY `uq_user_name_delete_time` (`user_name`, `delete_time`)
) COMMENT = '用户表';

插入第一条记录Sql

insert into t_user (id, user_name) values ('1', '张三');

逻辑删除第一条记录Sql

update t_user set is_delete = 1, delete_time = UNIX_TIMESTAMP(now()) where id = 1;

再次插入同名用户Sql

insert into t_user (id, user_name) values ('2', '张三');

此时,插入操作应该是成功的,因为虽然用户名相同,但是 delete_time 不一样,所以不会违反唯一性约束。

如果在mybatis中操作,不要用逻辑删除的注解,全部自己写代码实现功能。(个人体会)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值