如何删除所有相关行

时间:2015-02-04 09:32:28

标签: sql sql-server sql-server-2012

我有一个表 A ,其主键列为 a ,它是 B 表的forigen键(表B有主键b)和列a)。表B还有一个主键b,其中forc键为C表,依此类推。

现在,如果我想从表A中删除一行,那么它就不会允许我,因为它的依赖表B和表B依赖于表C.因此我必须首先从C中删除一行然后在B中删除一行

任何人都可以告诉我是否有任何方法可以直接删除而无需访问每个表并检查它是否有任何依赖关系然后删除

7 个答案:

答案 0 :(得分:3)

如果您不允许修改表格,可以查看EXISTS运算符。
仅当EXISTS内的查询返回至少1个结果时,它才允许您从表中删除行。您可以使用它来检查依赖关系。

您可以编写3个查询:

DELETE C c
WHERE EXISTS (SELECT 1
              FROM B b
              WHERE c.b = b.b
              AND EXISTS (SELECT 1
                          FROM A a
                          WHERE a.a = b.a
                          AND ... ));
DELETE B b
WHERE EXISTS (SELECT 1
              FROM A a
              WHERE a.a = b.a
              AND ...);

DELETE A a
WHERE ...

第一个将处理C中的记录,该记录引用B中引用A中要删除的记录的记录。
然后,您可以从B删除记录,因为C中没有更多依赖项  最后,您可以使用相同的逻辑从A删除记录。

答案 1 :(得分:2)

您可以使用级联Cascading Referential Integrity Constraints

<强>更新 您应该启用表B中的表A(PK)的级联参照完整性约束,其中A的ID是外键,类似于表B的PK,来自表C其中B的ID是外键

enter image description here

MSDN LIBRARY

CODE PROJECT ARTICALE

非常好的文章BLOG.SQL AUTHORITY

答案 2 :(得分:1)

您正在寻找的术语是级联&#39; - 你需要级联删除。您可以按照此处的说明启用它们:How do I use cascade delete with SQL Server?

答案 3 :(得分:1)

您可以使用级联参照完整性,请参阅此question。但是,要注意,过多的级联RI会在没有意识到的情况下造成很大的破坏!

答案 4 :(得分:1)

自动删除取决于您如何定义表之间的关系。

如果在尝试删除主表中的行时出现错误,那是因为您没有在删除关系中指定特殊操作。

我的意思是更改FK中的ON DELETEON UPDATE选项。这允许指定在删除或更新主表中的行时子行的内容。例如,ON DELETE CASCADE选项可以完全按照您的意愿执行。

例如:

CREATE TABLE Sales.TempSalesReason (
  TempID int NOT NULL, Name nvarchar(50
), 
CONSTRAINT PK_TempSales PRIMARY KEY NONCLUSTERED (TempID), 
CONSTRAINT FK_TempSales_SalesReason FOREIGN KEY (TempID) 
  REFERENCES Sales.SalesReason (SalesReasonID) 
  ON DELETE CASCADE
  ON UPDATE CASCADE
)

当你删除或修改主表中的行时,也会在子表上修改或删除该行。

相关文档:

答案 5 :(得分:0)

正如其他人已经指出的那样,cascade delete正是您所寻找的。在其中一条评论中,您提到过您不知道依赖项。这是一个列出依赖项的脚本

SELECT Db_name()                                   referencing_database_name, 
       Object_name (referencing_id)                referencing_entity_name, 
       Isnull(referenced_schema_name, 'dbo')       referenced_schema_name, 
       referenced_entity_name, 
       ao.type_desc                                referenced_entity_type, 
       Isnull(referenced_database_name, Db_name()) referenced_database_name 
FROM   sys.sql_expression_dependencies sed 
       JOIN sys.all_objects ao 
         ON sed.referenced_entity_name = ao.name  
WHERE ao.type_desc = 'USER_TABLE' 

答案 6 :(得分:0)

有一个存储过程'sp_fkeys',它将提供特定表的所有外键

exec sp_fkeys 'My_Table'

因此,您可以将输出保存到temp表,然后在游标中删除所有具有任何依赖关系的行。如果任何嵌套表也具有依赖关系,则您将执行相同操作,但对于嵌套表(递归)