sql—删除记录时如何检查外键约束是否失败

xkftehaa  于 2021-07-26  发布在  Java
关注(0)|答案(1)|浏览(385)

我在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 记录的内容将被更改,这是不应该做的。
因此,我想要一种在事务开始之前检查外键冲突的方法,而不需要实际删除记录

ncecgwcz

ncecgwcz1#

要实现您所要求的,只需检查子表中是否存在记录。

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+个子表,我会认真考虑总是将记录标记为已删除,而从不费心实际删除那些没有子记录的记录。一些额外的记录不太可能对您的数据库产生太大的影响。
实际上,根据我的经验,子表分为两类:
那些可以使用级联删除自动删除的
那些应该阻止我们删除父记录的
如果是这种情况,所需的检查应该变得更易于管理。
此外,对于这些情况,我建议将delete逻辑封装在存储过程中,以便将其保存在一个位置,并且在将来数据库方案发生更改时易于修改。
注意:我个人会 Deleted a列 bit 而不是一个 int 因为它更准确地反映了意图。

相关问题