1

我有一个带有 2 个表的 Microsoft SQL 数据库:狗和猫。

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

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

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

知道为什么会这样吗?我是否需要使用特殊的删除 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
4

6 回答 6

8

我已经解决了这个问题。

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

于 2011-01-19T13:33:38.167 回答
4

你能更具体地展示你的表格结构吗?听起来您的 PK/FK 方式错误。

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

于 2011-01-18T12:06:59.860 回答
1

您确定中的列fooddog的主键dog吗?如果您有一个名为 的表food,那么它的列food应该是 的主键和(以及)food的外键。然后使用删除将导致相应的行打开并被删除。dogcaton delete cascadefooddogcat

于 2011-01-18T12:07:44.970 回答
1

对于使用 SQL Server Management Studio 的人:

我绝对见过 UI 与数据库不同步的情况,即使您刷新了键列表或打开了一个全新的实例。

就我而言,我有一个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; --should be seeing this!

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

哪里可以清楚地看到DELETE CASCADE

如果您得到以下内容,则尽管 UI 可能会说什么,但级联规则实际上并未处于活动状态:

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

我刚刚删除了它(实际上必须删除它两次)并重新创建它以获得正确的 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 中创建新约束之前,我建议您始终首先检查孤立行。如果它们存在,您无论如何都必须删除它们。

于 2017-03-18T21:38:36.230 回答
0

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

于 2011-01-18T12:07:56.950 回答
0

这看起来工作得很好。

delete from Periods where PeriodID = 1

将从 Periods 中删除一行,并从 ExamPeriod = 1 的 Exams 中删除所有行

于 2011-01-18T14:09:51.100 回答