我已经在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
,所以如果外键失败,事务将中止,但是这里的问题是,如果外键没有失败,则会发生回滚,在这种情况下,{{ 1}}的记录将被更改,不应执行。
因此,我想要一种在事务开始前检查外键冲突而又不实际删除记录的方法
答案 0 :(得分:1)
要实现您要的内容,只需检查子表中是否存在记录,例如
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
列设为bit
而不是int
,因为它可以更准确地反映意图。