我是否需要在外键上指定ON DELETE NO ACTION?

时间:2013-07-31 17:10:51

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

我使用以下与SQL Server 2012一起使用的DDL:

CREATE TABLE Subject (
   [SubjectId] INT IDENTITY (1, 1) NOT NULL,
   [Name] NVARCHAR (50) Not NULL,
   CONSTRAINT [PK_Subject] PRIMARY KEY CLUSTERED ([SubjectId] ASC)
)           

CREATE TABLE Topic (
   [TopicId] INT IDENTITY (1, 1) NOT NULL,
   [Name] NVARCHAR (50) NOT NULL,
   [SubjectId] INT NOT NULL,
   CONSTRAINT [PK_Topic] PRIMARY KEY CLUSTERED ([TopicId] ASC)
)
ALTER TABLE [Topic] WITH CHECK ADD  CONSTRAINT [FK_TopicSubject] 
   FOREIGN KEY([SubjectId]) REFERENCES [Subject] ([SubjectId]) 
   ON DELETE NO ACTION

我想要的是,如果孩子中存在对该父项的引用,SQL Server会阻止我删除父项吗?例如,如果存在SubjectId为3的子女,我希望主题中的subjectID = 3删除失败。

为此,我不清楚,似乎无法找到答案。我是否需要添加" DELETE NO ACTION"或者我可以不删除这三个字。

我问这个问题是在一个类似的问题中,我有一个回应,我应该在父母上定义一个触发器。但是我认为只要定义外键就会阻止我在父母存在的情况下删除父项。

4 个答案:

答案 0 :(得分:29)

来自MSDN上的column_constraint页面:

  

ON DELETE {NO ACTION | CASCADE | SET NULL | SET DEFAULT}

     

指定更改的表中的行发生的操作(如果有)   行具有引用关系,并且删除引用的行   来自父表。默认值为无操作

所以,如果你愿意,你可以忽略ON DELETE NO ACTION,它会同样有效。

NO ACTION表示从Subject表中删除Topic表时不会发生任何事情。在这种情况下,如果给定SubjectId的主题中有一行,则无法在不破坏参照完整性的情况下从中删除,因此将回滚删除。

更多来自MSDN:

  

无操作 - SQL Server数据库引擎引发错误   回滚父表中行的删除操作。

答案 1 :(得分:4)

我打算告诉你,虽然你可以跳过删除没有动作,但这样做可能不符合你的最佳利益。在表定义中指定此项可能会阻止某人稍后添加级联删除,因为他们看到您打算不这样做。当您正确编写所有数据库对象的脚本并将它们放在源代码管理中并且代码审阅者会发现存在差异并询问其原因时,尤其如此。很多时候,人们太急于添加删除级联并销毁应该保留的数据(例如,对于不再有效的客户的财务记录)。他们这样做是因为他们得到的错误不会让他们删除,只是想摆脱它,而不是意识到这是从一个巨大的错误中拯救他们。至少如果你的表脚本中有Delete No Action的代码,未来的维护者会发现这是故意的,而不仅仅是你忘了设置级联删除。当然,如果你的dba不允许级联删除(因为许多没有并且有充分的理由!)那么这不是一个潜在的问题,但是指定你的意图通常是可维护性的好事。

答案 2 :(得分:0)

“无删除操作”实际上与“无删除”相同。

我同意最好使用它来阐明程序员在删除“标题”时对所需操作的想法,并决定如果存在与之相关的“行”,则不应删除“标题”。但是,我在Visual Studio中定义数据库,并且它拒绝将更改从“ ON DELETE”更新为“ ON DELETE NO ACTION”。刷新时它仍然处于“删除”状态。

答案 3 :(得分:-2)

您可以删除关键字(这是默认设置)

ON DELETE NO ACTION

最好指定这些行动

ON DELETE CASCADE

以下是更多信息:http://msdn.microsoft.com/en-us/library/aa933119%28v=sql.80%29.aspx

你必须编写一个触发器来确保不删除子行,因为我不认为SQL Server有ON DELETE RESTRICT的这个选项