数据库中唯一索引和逻辑删除字段的互斥

探讨了在数据库设计中,唯一索引与逻辑删除字段(ISACTIVE)之间的潜在冲突,尤其是在插入数据前进行重复检查时的问题。文章通过具体案例说明,当尝试插入的数据与已逻辑删除的数据在唯一索引字段上相同时,即使查询显示无重复,实际插入仍可能失败。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以下内容首发于我的个人博客网站:
http://riun.xyz


表中的唯一索引会和逻辑删除字段互斥,导致逻辑删除后的数据和要插入的数据出现重复索引时无法插入。

有如下表:

CREATE TABLE `pata_biz` (
  `ID` bigint(32) NOT NULL AUTO_INCREMENT COMMENT 'ID主键',
  `NAME` varchar(128) DEFAULT NULL COMMENT '业务线名称',
  `CODE` varchar(128) UNIQUE DEFAULT NULL COMMENT '业务线code',
  `BIZ_DESC` varchar(1024) DEFAULT NULL COMMENT '业务线描述'
  ...
  `ISACTIVE` tinyint(1) NOT NULL DEFAULT '1' COMMENT '逻辑删除',
  `INSERTTIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '插入时间',
  `UPDATETIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
);

其中code字段设置为了unique唯一属性,表中就会为此字段添加唯一索引。而表中又有逻辑删除字段ISACTIVE,当ISACTIVE为0时,此条数据就被认为已删除,永远不会再用到。在系统中所有条件只检索ISACTIVE为1的数据。

现在要求做插入操作之前,先查询表中有无name或者code相同的(name,code均不能相同),如果有相同的就不能插入,没有相同的,此sql会返回0表示可以插入。

查询的sql如下:

<sql id="insertCondition">
	<where>
		ISACTIVE  = 1 AND
		(`code` = #{code} OR `name` = #{name})
	</where>
</sql>
<select id="queryBizInfoCountByCodeNameForInsert" resultType="java.lang.Long" parameterType="com.ppd.bot.dao.entity.PataBiz">
	select count(*)
	from pata_biz
	<include refid="insertCondition"></include>
</select>

在执行查询时,如果数据库存在某条数据:name:testname1 code:1001 ISACTIVE:0 ,这条数据是被认为删除了的。然后尝试向表中插入一条数据:name:testname2 code:1001 此时使用queryBizInfoCountByCodeNameForInsert这个sql查询返回结果是0,因为上述数据的ISACTIVE是0查询时不会判断进去。但是真正执行插入sql语句时,数据库的唯一索引不会排除掉ISACTIVE为0的数据,就会因为code重复而无法插入直接报错。

这样看来数据库中好多限制都是理论限制,在实际应用中要根据场景分辨是否应该使用这些限制,尽量不要为数据库添加很强的限制条件,数据库只是存数据的,不做数据计算和判断。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值