删除包含子项和自引用约束的记录

时间:2013-08-12 21:02:01

标签: sql sql-server-2008-r2 entity-framework-5

所以我有以下表格(省略了不相关的列):

CREATE TABLE [dbo].[Step]
(
   [StepId] INT NOT NULL PRIMARY KEY IDENTITY, 
   [ParentStepId] INT NULL,

   CONSTRAINT [FK_Step_ParentStep] FOREIGN KEY ([ParentStepId]) REFERENCES [Step]([StepId])
)

CREATE TABLE [dbo].[StepInput]
(
   [StepInputId] INT NOT NULL PRIMARY KEY IDENTITY, 
   [StepId] INT NOT NULL, 
   [ChildStepId] INT NULL,

   CONSTRAINT [FK_StepInput_Step] FOREIGN KEY ([StepId]) REFERENCES [Step]([StepId]), 
   CONSTRAINT [FK_StepInput_ChildStep] FOREIGN KEY ([ChildStepId]) REFERENCES [Step]([StepId]),
)

有一个Step,它有零到多步StepInput。 StepInput有一个可选的子步骤,步骤有一个可选的父步骤(自引用)。

这可以按预期工作。我现在想要做的是删除一个步骤,并删除与该步骤相关联的所有StepInput,以及任何子步骤及其输入。

我正在使用实体框架5.是否有一种方便的方法来使用EF,或者我是否需要创建存储过程,在我的FK约束上设置级联选项,还是还有其他更好的解决方案?

我尝试过以各种方式使用ON DELETE CASCADE,但我没有尝试过。我还读到,在分层数据方面你不应该依赖级联删除,但是并不真正理解建议的替代方案(CTE?)

如果我添加ParentStepId列,它会使事情更简单吗?现在唯一真正的实用工具是确定步骤是否是顶级步骤,我可以轻松地使用位字段。没有父子关系,它们之间不涉及StepInput。

对于SQL,特别是SQL Server,我显然很绿,所以请记住你的答案;)

1 个答案:

答案 0 :(得分:1)

我尝试并创建了一个简单的过程,在给定stepId

的情况下删除所有行
DECLARE @stepId int
SET @stepId = 1

DECLARE @Delete TABLE
(
  id int
)

;WITH IdsToDelete (id)
AS (
  SELECT ChildStepId
  FROM StepInput
  WHERE StepId = @stepId
  UNION ALL
  SELECT s.ChildStepId
  FROM StepInput s
  INNER JOIN IdsToDelete I ON I.id = s.StepId
)



INSERT INTO @Delete (id)
  SELECT id
  FROM IdsToDelete



DELETE FROM StepInput WHERE StepId = @stepId OR StepId IN (SELECT Id FROM @Delete)
DELETE FROM Step WHERE StepId IN (SELECT Id FROM @Delete) OR StepId = @stepId

这个想法是创建一个递归的cte并存储你所有的id以删除然后将它们存储到一个声明的表中,如果cte在第一个语句之后将丢失它的数据。

然后你只需要删除该表上id的所有内容。我还删除了你在步骤表上的约束,这使得所有的删除都失败了。

我希望这次能说得对,我希望你能理解我在那里所做的一切。

干杯,