【问题标题】:sql delete cascade not workingsql删除级联不起作用
【发布时间】:2011-06-11 01:30:18
【问题描述】:

我有一个包含 2 个表的 Microsoft SQL 数据库:dog 和 cat。

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

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

但是“cat”表中的行确实会被删除,它们会保留下来。我使用 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

【问题讨论】:

  • 外键往哪个方向走? cat.food 引用 dog.food 还是 vv.?
  • 您能否发布两个表的完整 DDL(包括 FK 定义)?
  • 您发布的 DDL 对我来说很好用。当我删除 Period 时,它会删除相应的考试。那是你所期待的吗?你也有任何错误,或者它只是默默地失败了吗?
  • 在新的 2008 数据库中运行此脚本(并删除由于缺少表而无法创建的 FK),从 Periods 中删除会导致从 Exams 中删除匹配的行。所以肯定有别的东西
  • 马丁,这正是我所期待的。我没有收到任何错误 - 该行只是在期间而不是在考试中被删除。

标签: sql sql-server cascade cascading-deletes


【解决方案1】:

我已经解决了这个问题。

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • Dog.food 为主键,cat.food 为外键。
    • 我删除的行来自狗表。如何获取代码形式的表结构?
    • @jbkkd - 您可以右键单击 SSMS 中的表格并将表格“AS CREATE”写入窗口 - 发布这些脚本。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      对于使用 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 中创建新约束之前,我建议您始终首先检查孤立行。如果它们存在,您无论如何都必须删除它们。

      【讨论】:

        【解决方案5】:

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

        【讨论】:

        • 为什么会反过来呢?猫排取决于狗排。
        • @jbkkd - 如果您阅读答案,它会以 if 开头。您的示例有点不清楚,但 DDL 和您的评论清除了它。您确定您的表上没有导致问题的触发器。您确定启用了外键吗?
        • 阳性。我删除了考试表中的一行,例如,它是从考试题中的相关行中删除的,即具有外键的表。
        【解决方案6】:

        这个接缝工作得很好。

        delete from Periods where PeriodID = 1
        

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

        【讨论】:

        • 这正是我的问题,它不起作用。还有什么我需要检查的吗?
        猜你喜欢
        • 2013-06-22
        • 2013-03-03
        • 1970-01-01
        • 2012-11-18
        • 2018-06-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多