2016-07-12 22 views
2

我有这样的SQL脚本MSSQL创建数据库:引进国外KEY约束可能会导致循环或多个级联路径

CREATE TABLE ENTITY (
    ID    bigint IDENTITY(1,1)    NOT NULL, 
    NAME   nvarchar(255)     NOT NULL, 
    PARENT_ID  bigint       NULL 
) 
go 

ALTER TABLE ENTITY 
ADD CONSTRAINT PK_ENTITY PRIMARY KEY CLUSTERED (ID) 
WITH FILLFACTOR = 80 
go 

ALTER TABLE ENTITY 
ADD CONSTRAINT FK_ENTITY FOREIGN KEY (PARENT_ID) 
REFERENCES ENTITY (ID) ON DELETE CASCADE ON UPDATE CASCADE 
go 

通过设计,我想创建父 - >单表 所以孩子的关系,只是一些伪代码示例:

id | name | parent_id 
1 Mother  null 
2 Steve  1 
3 Jack  1 

我想如果需要 所有DELETE级联孩子的去除的母亲,但我安装这个剧本后,我收到:

Introducing FOREIGN KEY constraint 'FK_ENTITY' on table 'ENTITY' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. 

是否有任何解决方案,我可以如何正确实现这样的单表层次结构?

+2

你不能达到你想通过外键的级联什么SQL Server。确定的循环是最简单的循环 - 您希望在此表中删除,以便在同一个表中进一步删除。 SQL Server不支持。 –

+0

我将有不超过3步的递归数,也许我能够启用一些触发器或max_recursion参数?我相信微软有这样一个微不足道的任务(像MySQL一样) – ServerSideCat

+0

@ServerSideCat是的我认为你可以使用触发器'AFTER DELETE'手动实现它删除删除行 –

回答

0

看来SQL Server不会让级联递归外键删除,这样你可以写程序的删除操作,如下图所示:

CREATE PROC DeleteChildWithParent(@ID BIGINT) 
AS 

;WITH ChildToDelete AS (
    SELECT id, CAST(1 AS INT) AS ChildLevel 
    FROM ENTITY 
    WHERE id = @ID 
    UNION ALL 
    SELECT e.id, C.ChildLevel + 1 
    FROM ENTITY E 
      JOIN ChildToDelete C ON e.PARENT_ID = C.ID AND E.PARENT_ID <> E.ID 
) 

SELECT id, ROW_NUMBER() OVER (ORDER BY ChildLevel DESC) Ord 
INTO #ChildToDelete 
FROM ChildToDelete 

DECLARE @count INT = 1, @max INT = @@ROWCOUNT; 

WHILE @count <= @max 
BEGIN 
    DELETE ENTITY WHERE id = (SELECT id FROM #ChildToDelete WHERE Ord = @count); 
    SET @count = @count + 1; 
END; 
GO 
+2

你知道,可以在没有'WHILE'循环的情况下写入'DELETE'。 '从实体中删除Entity.id IN(SELECT id FROM #ChildToDelete)'。最有可能的是,它甚至没有必要使用临时表... –

+0

我用虽然删除记录分别从孩子到父母和使用临时表来找出这些优先事项,例如,删除ID为1的母亲,它会删除史蒂夫和杰克,然后删除母亲 –

相关问题