sql - 删除记录时如何检查外键约束是否失败
问题描述
我在 SQL Server 中创建了一个数据库,前端是 PHP - CodeIgniter。在数据库中,我用其他表创建了多个外键。现在,当用户尝试删除记录时,而不是真正删除我想将记录标记为deleted = 1
,只有在子表中没有可用的参考记录时才应该这样做。以下是示例表:
Parent_Table
Id INT(PK), Name Varchar, deleted INT
Child_Table
Id INT(PK), FK_Parent_Table_ID INT, address varchar, deleted INT
以上只是我的表格的示例。现在,每当用户尝试从父表中删除记录时,外键都会检查约束,然后删除该记录,这里我希望将其标记为deleted = 1
.
我尝试过使用transaction->start
,transaction->complete
所以如果外键失败,事务就会中止,但这里的问题是,如果外键没有失败,那么将发生回滚,在这种情况下PRIMARY KEY
,记录的内容将被更改,不应进行。
所以,我想要一种在事务开始之前检查外键冲突而不实际删除记录的方法
解决方案
要实现您的要求,只需检查子表中是否存在记录,例如
declare @RecordToDelete int = 123;
-- Delete the record if no child records exist
delete
from Parent_Table
where id = @RecordToDelete
and not exists (select 1 from Child_Table where FK_Parent_Table_ID = @RecordToDelete);
-- Flag the record as deleted if child records exist
update Parent_Table set
Deleted = 1
where id = @RecordToDelete
and exists (select 1 from Child_Table where FK_Parent_Table_ID = @RecordToDelete);
取决于您是否真的需要保留记录,因为您始终可以使用级联删除创建外键。
对于 15 个以上的子表,我会认真考虑始终将记录标记为已删除,而从不打扰实际删除那些没有子记录的记录。一些额外的记录不太可能对您的数据库产生太大影响。
实际上,根据我的经验,子表分为两类:
- 可以使用级联删除自动删除的那些
- 那些应该阻止我们删除父记录的
如果是这种情况,所需的检查应该变得更易于管理。
同样对于这些情况,我建议将删除逻辑封装在存储过程中,以便将其全部保存在一个地方,并且如果将来数据库方案发生更改,则易于修改。
注意:就我个人而言,我会将Deleted
列设为 abit
而不是 a,int
因为它更准确地反映了意图。
推荐阅读
- java - 如何处理继承类型的多种处理方法?
- python - tf.reshape 没有为第一个元素提供 ?(None)
- reactjs - 升级 react-native 0.59 到 0.61 的 react-native-navigation 出现错误
- php - 如何在临时文件 PHP 上写入图像
- python - 如何在 Django 中用户未输入数据的 POST 请求中发送数据
- .net-core - HealthChecksUI + 内存 (GCInfo)
- react-native - 如何运行旧版本的 react native
- sql - oracle函数需要返回两种表类型
- go - 使用 timer.Reset() 的计时器示例未按描述工作
- python - 如何以编程方式创建客户?