从表A和B中删除许多记录,其中一个FK到表B.

时间:2012-08-07 12:59:50

标签: sql sql-server nhibernate

我有两张桌子:A和B

A包含以下列:

Id [uniqueIdentifier] -PK
checkpointId [numeric(20,0)]

B包含以下内容:

Id [uniqueIdentifier] – PK
A_id (FK, uniqueIdentifier)

B从A_id列(FK)

引用A

问题: 我想从表A中删除其checkpoint_id小于X

的所有记录
delete from CheckpointStorageObject where checkpointIdentifierIdentifier <= 1000

但自"The primary key value cannot be deleted because references to this key still exist"

以来我无法做到

我尝试在没有连接的情况下首先从B表中删除:

DELETE FROM CheckpointToProtectionGroup 
WHERE EXIST (SELECT * from CheckpointStorageObject 
             WHERE CheckpointStorageObject.CheckpointIdentifierIdentifier <= 1000)

但它不起作用。

我该怎么办? 是否可以使用一个执行命令从两个表中删除?

结果删除的记录可能非常大 - 每张表中的记录超过30K。

3 个答案:

答案 0 :(得分:2)

试试这个:

首先从tableB中删除:

delete from tableB where A_id IN (Select Id from tableA where checkpointId <= 1000)

然后从tableA中删除:

delete from tableA where checkpointId <= 1000

答案 1 :(得分:0)

您首先必须删除表B中的条目

delete from tableB where A_id IN (Select Id from tableA where checkpointIdentifierIdentifier <= 1000)

完成后,您可以通过检查表B中不再包含的ID

从表A中删除
delete from tableA where Id not in (select A_id from tableB)

答案 2 :(得分:0)

您的第二个查询存在一些缺陷:

  • 它是EXISTS而不是EXIST

  • 您需要指定2个表之间的连接条件。在像这样的相关子查询中,你可以在WHERE子句中添加条件

  • 为表格添加别名,减少代码并使其更具可读性,尤其是使用如此长的名称,这也是很有用的

  • 将2个语句包含在一个事务中,这样您就可以确定它成功 - 并从两个表中删除 - 或者失败并且不删除任何内容。如果您不使用事务,则第二次删除可能不会成功,如果在2次删除之间的较短时间内,在表B中插入一行并且引用表A中的第二条语句将尝试删除的行

因此,请先从表B(CheckpointToProtectionGroup)中删除:

BEGIN TRANSACTION

    DELETE FROM CheckpointToProtectionGroup AS b
    WHERE EXISTS                                  --- EXISTS
          ( SELECT * 
            FROM CheckpointStorageObject AS a
            WHERE a.id = b.A_id                   --- join condition
              AND a.CheckpointId <= 1000
          ) ;

然后从表A(CheckpointStorageObject):

    DELETE FROM CheckpointStorageObject
    WHERE CheckpointId <= 1000 ;

COMMIT TRANSACTION ;