我有一个表在其他几个表中用作外键。如果只在一个特定的表中引用该表,我希望允许删除并在删除时级联。但是,如果其他表中存在引用,则删除应该失败。
我想通过尝试删除每条记录来测试我的数据集的引用完整性。除最后一个记录外,不应删除任何记录。但是,当我尝试删除每条记录时,它会出错(如预期的那样)并终止语句的其余部分。
如何编写试图删除表中每条记录的脚本,而不是在第一次错误时终止该语句?
亲切的问候,
下流
编辑:
我想要做这样的事情的原因是因为业务用户添加了大量重复数据(即:搜索某人并单击“添加为新”而不是“选择”)。现在我们可能有10个人,只有一个名字,与其他表没有关系。我希望这可以澄清任何混乱。
答案 0 :(得分:3)
我玩弄了不同的想法。这是最直接的方式。但是,这是非常昂贵的。同样,这是尝试删除未使用的重复数据。 1,000条记录花了8分钟。谁能想到一种更有效的方法呢?
DECLARE @DeletedID Int
DECLARE ItemsToDelete SCROLL CurSor For
SELECT ID FROM ParentTable
Open ItemsToDelete
FETCH NEXT FROM ItemsToDelete INTO @DeletedID
While @@FETCH_STATUS = 0
BEGIN
BEGIN TRY
--ATTEMPT TO DELETE
DELETE FROM ParentTable WHERE ID = @DeletedID;
END TRY
BEGIN CATCH
--DO NOTHING
END CATCH
--FETCH NEXT ROW
FETCH NEXT FROM ItemsToDelete INTO @DeletedID
END
Close ItemsToDelete
Deallocate ItemsToDelete
答案 1 :(得分:1)
带上一粒盐:我实际上不是DBA,从未使用过SQL Server。但是:
你实际上违反了两条不同的规则:
听起来就像设置了引用约束(在子表中)时,它们是使用选项RESTRICT
或NO ACTION
创建的。这意味着,当存在子行时,尝试从父表中删除将导致失败。但问题是,您希望在特定的表上允许删除并传播它们(选项CASCADE
)。因此,对于仅那些要删除应的表,请更改引用约束以使用CASCADE
。否则,使用(已存在的)错误阻止删除。
至于处理突然出现的'例外'......这里有一些处理它们的方法:
答案 2 :(得分:1)
好吧,SQL中的每个语句都被视为事务,因此,如果您尝试删除多个记录,并且在考虑完整性规则时遇到错误,则到目前为止所做的每个更改都将被回滚。您可能要做的是编写将从引用表(具有外键值(在您的情况下为T_child表)中具有值的表中删除数据的查询,然后从T_parent表中删除数据。
总计:首先检查T_child表中是否有要删除的记录,然后从T_parent表中删除记录,以避免事务失败。
希望这有帮助。
(如果我错了,请纠正我)
答案 3 :(得分:1)
这里有一些选择。你的问题有点含糊不清,所以我想先重新讨论你的用例(我会按照我的理解回答你的问题)。
使用案例
数据库由几个表T_Parent,T_Child1,T_Child2,T_Child3组成。一组完整的数据将在所有4个表中都有记录。鉴于业务需求,我们经常会得到需要在以后删除的部分数据。例如,T_parent和T_Child2可以获得数据,但不能获得TC1和TC3。
我需要能够检查部分数据,如果找到则删除所有部分数据(在我的示例中为T_Parent和T_Child 2,但它可以是TP和TC3,或其他组合)。
@ribald - 我的理解是否正确?