从表中删除记录时的前置或后置检查
Posted
技术标签:
【中文标题】从表中删除记录时的前置或后置检查【英文标题】:Pre or post check when deleting records from a table 【发布时间】:2012-06-08 14:06:11 【问题描述】:对于经常删除记录的 Web 应用程序,如果我们考虑性能,什么是最好的?
检查该记录是否与其他表有关联,防止用户删除。
ex : 查询会是这样的
if not exist(select * from table1 where tableX_id = @id) and
not exist(select * from table2 where tableX_id = @id)
...
then
delete from tableX where id = @id
或
执行delete
并让RDBMS 由于foriegn key
约束而引发错误
try
Service.DeleteRecord(id)
catch
Handle the error here
在这种情况下,查询会很简单
delete from TableX where id = @id
【问题讨论】:
为什么不能对相关表使用级联删除? @Arion 我不想删除其他表中引用的记录 你为什么不想要那个?我的意思是您在删除时不必检查任何内容。您不必捕获任何错误。你可以让 sql-server 做“工作” @anouar204: CASCADE 被分配给单个 FK 引用,默认情况下它不会删除 所有内容,只会删除 FK 所源自的表。 我想说所有这些逻辑都应该在您调用以执行删除的任何存储过程中。让它只返回删除的行数并在代码中检查。如果您只是编写直接删除而不使用存储过程,则将代码转换为存储过程。 【参考方案1】:如果目标是仅在实际运行删除会产生错误的情况下防止行被删除,因为它被其他表引用,那么我建议您在让 SQL Server 为您检查之前检查违规情况。 I've done some testing on this 并让 SQL 捕获错误或仅使用 TRY/CATCH 可能会更昂贵,如果您预计即使是中等数量的失败也是如此。有了适当的索引,执行检查的额外成本可以忽略不计;但是,不进行检查的成本肯定是可以忽略不计的。
【讨论】:
检查然后删除需要一个合适的事务(以及合适的隔离和锁定)来防止竞争 - 否则,你必须处理来自删除的错误的可能性。 在您的回答中“使用适当的索引”会产生重大影响,并且在其他情况下很可能会适得其反,或者由于其他业务原因根本无法做到。 @Damien_The_Unbeliever 是的,我不是说它是替代品,您可能仍需要尝试/捕获或其他错误处理,但如果在检查时行是否验证失败进入删除阶段是没有意义的,以防万一其他事务使删除成功成为可能。仍然使用 try/catch(或仅在验证检查成功时执行删除)仍将捕获在检查和删除之间删除无效的边缘情况。 您是否认为如果我们检查许多表,这些检查的成本仍然可以忽略不计? @anouar204 不确定我们是否可以就“可忽略”的含义达成一致,或者您编写的检查将如何优化,但如果 SQL Server 在尝试删除时必须进行这些检查,那该怎么办你在省钱吗?检查的好处是您可以自定义它们,以便首先检查最便宜的表(您无法控制违规),添加索引以支持您的检查(违规可能不会使用)等等。 【参考方案2】:我会使用数据库触发器(或 ON CASCADE DELETE)来处理任何关系——可用的工具取决于您的 RDBMS。
【讨论】:
我不想删除其他表中引用的记录 既然您特意询问了检查与其他表的关系,您打算如何处理孤立的相关记录? 我认为这就是重点 - 如果他删除 X 中的一行,而 Y 中没有行指向它,它不会留下任何孤儿。 我要求检查以删除或不删除记录不进行清理 好的,既然您已经编辑了原始帖子,我更了解您的情况。由于这是删除记录与否的直接问题,因此我将执行存储过程中的逻辑并向应用程序返回布尔值、错误消息或其他指示符。【参考方案3】:显然,执行删除并让 RDBMS 处理业务。通过自己实施检查,您会招致 RDBMS 无论如何都会执行的额外操作。
【讨论】:
以上是关于从表中删除记录时的前置或后置检查的主要内容,如果未能解决你的问题,请参考以下文章