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

Sql 删除记录时如何检查外键约束是否失败,sql,sql-server,codeigniter,sql-server-2005,Sql,Sql Server,Codeigniter,Sql Server 2005,我已经在SQLServer中创建了一个数据库,前端是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

我已经在SQLServer中创建了一个数据库,前端是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
,因此如果外键失败,事务将被中止,但这里的问题是如果外键没有失败,那么将发生回滚,在这种情况下,记录的
主键将被更改,而不应该这样做


因此,我想要一种在事务开始之前检查外键冲突的方法,而不实际删除记录

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

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个+子表,我会认真考虑只将记录标记为已删除,并且从不费心去删除那些没有子记录的记录。一些额外的记录不太可能对您的数据库产生太大的影响


实际上,根据我的经验,子表分为两类:

  • 那些可以使用级联删除自动删除的
  • 那些应该阻止我们删除父记录的
如果是这种情况,所需的检查应变得更易于管理


此外,对于这些情况,我建议将删除逻辑封装在存储过程中,以便将其保存在一个位置,并且在将来数据库方案发生更改时易于修改



注意:我个人会将
删除的
列设为
而不是
int
,因为它更准确地反映了意图。

我理解你的意思,但在我的情况下,有超过15个以上的表被引用,因此不太可能通过查询检查每个表。@Niks Its完全可能,这是唯一的方法。@Niks您还需要确保您的问题包含所有相关信息,即子表的数量。@Niks。这似乎回答了您实际提出的问题。如果确实如此,那么你应该接受它。如果你没有问你想问的问题,那就问一个新问题。不要玩“猜猜我真正的问题”的游戏。