2

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

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,它有零对多的 StepInputs。StepInput 有一个可选的子 Step,Step 有一个可选的父 Step(自引用)。

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

我正在使用 Entity Framework 5。是否有使用 EF 执行此操作的便捷方法,或者我是否需要创建存储过程、在我的 FK 约束上设置级联选项,或者是否有其他更好的解决方案?

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

如果我取消 ParentStepId 列,事情会变得更简单吗?现在唯一真正有用的是确定该步骤是否是顶级步骤,我可能可以很容易地使用位字段。没有不涉及 StepInput 的父子关系。

当谈到一般的 SQL 和特别是 SQL Server 时,我显然很绿色,所以请记住你的答案;)

4

1 回答 1

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 所在的所有内容。我还删除了您在步骤表上的约束,这使所有删除都失败了。

我希望这次我做对了,我希望你明白我在那里做了什么。

干杯,

于 2013-08-12T22:51:00.937 回答