简体   繁体   English

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

[英]How to check if foreign key constraint fails when deleting record

I have created a database in SQL Server and front end is PHP - CodeIgniter.我在 SQL 服务器中创建了一个数据库,前端是 PHP - CodeIgniter。 In the database I have created multiple foreign keys with other tables.在数据库中,我用其他表创建了多个外键。 Now when the user tries to delete the record, instead of really deleting I want to flag the record as deleted = 1 , this should only be done when there will be no reference records are available in child table.现在,当用户尝试删除记录时,而不是真正删除我想将记录标记为deleted = 1 ,只有在子表中没有可用的参考记录时才应该这样做。 Below are example tables:以下是示例表:

Parent_Table
Id INT(PK), Name Varchar, deleted INT

Child_Table
Id INT(PK), FK_Parent_Table_ID INT, address varchar, deleted INT

Above is just example of my tables.以上只是我的表格的示例。 Now whenever a user tries to delete a record from the parent table foreign key will check for constraint and then delete the record, here instead of actual deletion I want it flag as deleted = 1 .现在,每当用户尝试从父表中删除记录时,外键都会检查约束,然后删除记录,在这里,我希望将其标记为deleted = 1而不是实际删除。

I have tried using transaction->start and transaction->complete so if foreign key fails the transaction gets aborted but here the problem is if the foreign key not failing then the rollback will occur and in that case the PRIMARY KEY of the record will be changed that should not be done.我尝试过使用transaction->starttransaction->complete ,所以如果外键失败,事务将中止,但这里的问题是,如果外键没有失败,那么将发生回滚,在这种情况下,记录的PRIMARY KEY将是不应该做的改变。

So, I want a way to check the foreign key conflict before transaction starts without actual deletion of the record所以,我想要一种在事务开始之前检查外键冲突而不实际删除记录的方法

To implement what you are asking, just check for the existence of a record in the child table eg要实现您的要求,只需检查子表中是否存在记录,例如

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);

Depending on whether you really need to keep the record, because you could always create your foreign keys with a cascade delete.取决于您是否真的需要保留记录,因为您始终可以使用级联删除创建外键。

With 15+ child tables I would seriously consider just always flagging the record as deleted and never bothering to actually delete those without child records.对于 15 个以上的子表,我会认真考虑始终将记录标记为已删除,并且从不费心实际删除那些没有子记录的记录。 A few extra records is unlikely to make much difference to your database.一些额外的记录不太可能对您的数据库产生太大影响。


Actually in my experience child tables fall into 2 categories:实际上,根据我的经验,子表分为两类:

  • Those that can automatically be deleted using a cascade delete可以使用级联删除自动删除的那些
  • Those that should prevent us from deleting the parent record那些应该阻止我们删除父记录的

If this is the case the checks required should become more manageable.如果是这种情况,所需的检查应该变得更易于管理。


Also for these situations I recommend encapsulating the delete logic within a stored procedure in order to keep it all in one place, and be easy to modify if the database schemes changes in future.同样对于这些情况,我建议将删除逻辑封装在存储过程中,以便将其全部保存在一个地方,并且如果将来数据库方案发生更改,则易于修改。


Note: Personally I would make the Deleted column a bit rather than an int as it more accurately reflects the intention.注意:我个人会使Deletedbit而不是int ,因为它更准确地反映了意图。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM