如何在SQL Server中使用级联删除?


332

我有2个表:T1和T2,它们是具有数据的现有表。T1和T2之间存在一对多关系。当删除T1中的记录时,如何更改表定义以在SQL Server中执行级联删除,T2中的所有相关记录也都删除了。

它们之间存在外部约束。我不想删除表或创建触发器来删除T2。例如,当我删除员工时,所有复查记录也应消失。

T1-员工,

Employee ID      
Name
Status

T2-效果评论,

Employee ID - 2009 Review
Employee ID - 2010 Review

Answers:


362

您将需要

  • 删除现有的外键约束,
  • ON DELETE CASCADE启用设置添加一个新的。

就像是:

ALTER TABLE dbo.T2
   DROP CONSTRAINT FK_T1_T2   -- or whatever it's called

ALTER TABLE dbo.T2
   ADD CONSTRAINT FK_T1_T2_Cascade
   FOREIGN KEY (EmployeeID) REFERENCES dbo.T1(EmployeeID) ON DELETE CASCADE

3
我和我的团队就是这样做的。我们必须放弃约束并重新添加约束。这对我们有用。
Daniel L. VanDenBosch

2
如何支持硬删除?软删除永远不会有约束问题。似乎与我相反。
Maxx

2
@Maxx在硬删除中,您删除一条记录,而不必担心孤立的寄存器,而在软删除中,您需要手动进行。
罗纳尔多·阿劳霍·阿尔维斯

319

要将“层叠删除”添加到SQL Server Management Studio中的现有外键,请执行以下操作:

首先,选择您的外键,然后在新的“查询”窗口中打开它的“ DROP and Create To ..”。

在此处输入图片说明

然后,只需添加ON DELETE CASCADEADD CONSTRAINT命令:

ñ 并点击“执行”按钮以运行此查询。

顺便说一句,要获取外键的列表,并查看打开了“级联删除”的外键,可以运行以下脚本:

SELECT 
   OBJECT_NAME(f.parent_object_id) AS 'Table name',
   COL_NAME(fc.parent_object_id,fc.parent_column_id) AS 'Field name',
   delete_referential_action_desc AS 'On Delete'
FROM sys.foreign_keys AS f,
     sys.foreign_key_columns AS fc,
     sys.tables t 
WHERE f.OBJECT_ID = fc.constraint_object_id
AND t.OBJECT_ID = fc.referenced_object_id
ORDER BY 1

并且,如果您发现DROP由于外键约束而无法创建特定的表,但无法确定是哪个FK导致了问题,则可以运行以下命令:

sp_help 'TableName'

该文章中的SQL列出了引用特定表的所有FK。

希望所有这些都对您有所帮助。

为长手指道歉。我只是想指出一点。


163

您可以使用SQL Server Management Studio执行此操作。

→右键单击表设计并转到“关系”,然后在左侧窗格中选择外键,然后在右侧窗格中,展开菜单“ INSERT and UPDATE specification”,然后选择“ Cascade”作为“删除规则”。

SQL Server管理Studio


嗨,4和4之间有什么区别?启用层叠会使您很容易删除表中的所有数据。我如何查看此表上的所有依赖项/ fk键,而不是此表中的键。即使删除所有FK的我仍然得到错误之后
阿吉

@aggie-您可以通过以下方式检查依赖项:-右键单击表->“ View Dependencies”,sql server也会为您提供表名和列名的详细错误,例如“ DELETE语句与REFERENCE约束” FK_Child1_Parent1“冲突。在数据库“ TESTDB”的表“ dbo.Child1”的“ Parent1ID”列中发生了冲突。
Palanikumar,2015年

@aggie-第四种情况是“设置默认值”是,您必须在“外键”列中设置默认约束,当我们删除父级时,默认值将在子表中替换。(注:默认值必须与父表匹配。)欲了解更多信息请访问mssqltips.com/sqlservertip/2365/...
Palanikumar

这非常有帮助。我想知道为什么没有插入规则?换句话说,当我向T1添加一行时,我希望T2中的相应条目自动创建。
罗伯特M.16年

@RobertM。因为那没有意义。它怎么知道要插入什么值?您也许可以使用INSERT触发器生成子行,然后尝试进行研究。
Dan Bechard

47

使用类似

ALTER TABLE T2
ADD CONSTRAINT fk_employee
FOREIGN KEY (employeeID)
REFERENCES T1 (employeeID)
ON DELETE CASCADE;

填写正确的列名,您将被设置。正如mark_s正确指出的那样,如果您已经有了外键约束,则可能需要先删除旧的约束,然后再创建新的约束。


41
@marc_s-实际上,您可以在两边完全相同的列上添加第二个外键,它可以正常工作。如果在没有停机时间的生产环境中工作,则最好引入级联的新FK,然后放下旧的FK,而不是在没有FK的情况下在桌子上放个窗户。(刚刚在SQL 2008上进行了测试)
Damien_The_Unbeliever 2011年

这是对的。我试过了,它有效。无需删除第一个外键约束。谢谢回复。
Bichvan Nguyen 2011年

15

首先启用ONCascade属性:

1,放弃现有的外键约束

2.添加一个新的启用ON DELETE CASCADE设置

例如:

IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE parent_object_id = OBJECT_ID(N'dbo.Response'))
 BEGIN 

ALTER TABLE [dbo].[Response] DROP CONSTRAINT [FK_Response_Request]  

ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END

ELSE

 BEGIN 
 ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END

第二个禁用ONCascade属性:

1,放弃现有的外键约束

2.添加一个新的启用ON DELETE NO ACTION设置

例如:

IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE parent_object_id = OBJECT_ID(N'dbo.Response'))
 BEGIN 
ALTER TABLE [dbo].[Response] DROP CONSTRAINT [FK_Response_Request]  

ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END

ELSE

 BEGIN 
 ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE NO ACTION 
END

15

ON DELETE CASCADE
它指定在删除父数据时删除子数据。

CREATE TABLE products
( product_id INT PRIMARY KEY,
  product_name VARCHAR(50) NOT NULL,
  category VARCHAR(25)
);

CREATE TABLE inventory
( inventory_id INT PRIMARY KEY,
  product_id INT NOT NULL,
  quantity INT,
  min_level INT,
  max_level INT,
  CONSTRAINT fk_inv_product_id
    FOREIGN KEY (product_id)
    REFERENCES products (product_id)
    ON DELETE CASCADE
);

对于此外键,我们指定了ON DELETE CASCADE子句,当删除父表中的数据时,该子句告诉SQL Server删除子表中的相应记录。因此,在此示例中,如果从产品表中删除了product_id值,则库存表中使用该product_id的相应记录也将被删除。


-2

如果一对多关系是从T1到T2,则它不表示一个函数,因此不能用来推论或推断一个反函数,以保证所得的T2值不会忽略T1的元组与T2演绎地有效,因为没有演绎有效的逆函数。(表示函数是主键的目的。)SQL的答案是可以的。关系型思维的答案是不,你做不到。参见Codd 1970中的歧义点。从T1到T2,这种关系必须是多对一的。


-10

我认为您不能仅删除表属性,如果这是实际的生产数据,那么只需删除不影响表架构的内容即可。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.