sql删除级联不起作用

时间:2011-01-18 12:03:19

标签: sql sql-server cascade cascading-deletes

我有一个带有2个表的Microsoft SQL数据库:dog and cat。

“dog”表有一个名为“food”的主键列,它与“cat”表中的一个名为“food”的列相关,该表用作外键。

表之间的关系有一个“on delete cascade”规则集,所以当我从“dog”表中删除一行时,“cat”表中的重定义行也应该被删除。

但是“cat”表中的行会删除net,它们会保留。我使用Microsoft SQL数据库管理器删除“dog”表中的行。

知道为什么会这样吗?我是否需要使用特殊的delete sql命令以这种方式删除行?

//修改

表格的脚本是:

USE [VELES]
GO
/****** Object:  Table [dbo].[Periods]    Script Date: 01/18/2011 14:52:19 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Periods](
    [PeriodID] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
    [PeriodName] [nvarchar](50) COLLATE Hebrew_CS_AS NULL,
    [PeriodStartDate] [smalldatetime] NOT NULL,
    [PeriodEndDate] [smalldatetime] NOT NULL,
 CONSTRAINT [PK_Periods] PRIMARY KEY CLUSTERED 
(
    [PeriodID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]


USE [VELES]
GO
/****** Object:  Table [dbo].[Exams]    Script Date: 01/18/2011 14:55:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Exams](
    [ExamID] [int] IDENTITY(1,1) NOT NULL,
    [ExamUserID] [char](7) COLLATE Hebrew_CS_AS NOT NULL,
    [ExamBase] [tinyint] NOT NULL,
    [ExamUserTimesAccessed] [tinyint] NULL,
    [ExamMaxTimesToOpen] [tinyint] NOT NULL,
    [ExamUserLastTimeOpened] [datetime] NULL,
    [ExamUserLastTimeFinished] [datetime] NULL,
    [ExamTimeToFinish] [int] NOT NULL,
    [ExamPassGrade] [int] NOT NULL,
    [ExamPeriod] [int] NOT NULL,
    [ExamUserRank] [tinyint] NULL,
 CONSTRAINT [PK_Exams] PRIMARY KEY CLUSTERED 
(
    [ExamID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF
GO
USE [VELES]
GO
ALTER TABLE [dbo].[Exams]  WITH CHECK ADD  CONSTRAINT [FK_Exams_Bases] FOREIGN KEY([ExamBase])
REFERENCES [dbo].[Bases] ([BaseID])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[Exams]  WITH NOCHECK ADD  CONSTRAINT [FK_Exams_Periods] FOREIGN KEY([ExamPeriod])
REFERENCES [dbo].[Periods] ([PeriodID])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[Exams]  WITH NOCHECK ADD  CONSTRAINT [FK_Exams_Users] FOREIGN KEY([ExamUserID])
REFERENCES [dbo].[Users] ([UserID])
ON UPDATE CASCADE
ON DELETE CASCADE
NOT FOR REPLICATION 
GO
ALTER TABLE [dbo].[Exams] CHECK CONSTRAINT [FK_Exams_Users]
GO
ALTER TABLE [dbo].[Exams]  WITH CHECK ADD  CONSTRAINT [UserRanks_Exams_FK1] FOREIGN KEY([ExamUserRank])
REFERENCES [dbo].[UserRanks] ([RankID])
ON UPDATE CASCADE
ON DELETE CASCADE

6 个答案:

答案 0 :(得分:5)

我已经解决了这个问题。

在关系窗口中,有一个名为Enforce Foreign Key Constraint的选项,设置为“否”。 我将其设置为“是”,现在行删除效果很好。

答案 1 :(得分:4)

你能更具体地展示你的桌面结构吗? 这听起来像PK / FK错误的方式。

删除FK部分(子)不会对PK记录(父级)执行任何操作。 只有当您删除PK记录时,它才会级联到链接到它的子记录。

答案 2 :(得分:1)

您确定food中的dog列是dog的主键吗?如果您有一个名为food的表,那么它的列food应该是food的主键和dog的外键(以及cat )。然后,on delete cascade上的food次删除会导致dogcat上的相应行被删除。

答案 3 :(得分:1)

对于使用SQL Server Management Studio的人员:

我确实看到过用户界面与数据库不同步的情况,即使您刷新了密钥列表或打开了一个全新的实例。

对于我的情况,我有一个Order,其中有DiscountedItem个子项目。

检查相关内容是否不同步的方法是右键单击FK_DiscountedItem_Order并选择Script Key as CREATE To Clipboard,然后检查您获得的内容:

得到这样的东西:

ALTER TABLE [dbo].[DiscountedItem]  WITH NOCHECK ADD  CONSTRAINT    [FK_DiscountedItem_Order] FOREIGN KEY([OrderId])
REFERENCES [dbo].[Order] ([OrderId])
ON DELETE CASCADE
GO

ALTER TABLE [dbo].[DiscountedItem] CHECK CONSTRAINT [FK_DiscountedItem_Order]
GO

您可以清楚地看到DELETE CASCADE

如果您得到类似以下内容的内容,那么尽管用户界面可能会说出来,但级联规则实际上并不活跃:

ALTER TABLE [dbo].[DiscountedItem]  WITH CHECK ADD  CONSTRAINT [FK_DiscountedItem_Order] FOREIGN KEY([OrderId])
REFERENCES [dbo].[Order] ([OrderId])
GO

我刚删除它(必须实际删除它两次)并重新创建它以获得正确的SQL。

你可能需要运行这样的东西来检查“孤儿”这样的事情。子行:

select * from DiscountedItem where DiscountedItem.orderid not in (select orderid from [order])

然后如果这样做是安全的:

delete from DiscountedItem where DiscountedItem.orderid not in (select orderid from [order])

为什么会这样?

只是添加了约束并立即得到了外键错误,因为我有孤立的行。然后有些东西感到困惑,并认为级联已启用。

因此,在UI中创建新约束之前,我建议您始终先检查孤立行。如果它们存在,你将不得不删除它们。

答案 4 :(得分:0)

如果cat表是外键的键,那么从dog中删除一行不会从cat中删除一行,而是反过来。

答案 5 :(得分:0)

这种接缝工作得很好。

delete from Periods where PeriodID = 1

将从句点中删除一行,并从具有ExamPeriod = 1

的考试中删除所有行