如何删除sql邻接列表中给定root的所有节点

时间:2016-07-12 07:47:16

标签: sql sql-server sql-server-2008 hierarchical-data

有这个表:

enter image description here

我想通过发送查询ID = 1来删除根节点 我希望这个id的所有子节点也将被删除。

我该怎么办?

2 个答案:

答案 0 :(得分:2)

假设您有以下数据:

enter image description here

并且您想要删除记录2.1及其所有后代(仅在此情况下为2.1.3)。您可以使用以下代码获取需要删除的IDs

WITH DataSource ([ID], [HierarchyLevel]) AS
(
    SELECT [ID]
          ,CAST(REPLACE('/' + [Name] + '/', '.', '/') AS HIERARCHYID)
    FROM @DataSource
)
SELECT [ID]
      ,[HierarchyLevel].ToString()
FROM DataSource
WHERE [HierarchyLevel].IsDescendantOf('/2/1/') = 1;

enter image description here

基本上,我们会将您的记录转换为hierarchy id类型,并使用内置IsDescendantOf函数获取该节点的所有childs

这是完整的工作示例:

DECLARE @DataSource TABLE
(
    [ID] TINYINT
   ,[Name] VARCHAR(12)
   ,[Owner] VARCHAR(12)
   ,[Parent] INT
);

INSERT INTO @DataSource ([ID], [Name], [Owner], [Parent])
VALUES (1, '1', '1', NULL)
      ,(2, '1.1', '1.1', 1)
      ,(3, '1.1.1', '1.1.1', 2)
      ,(4, '2', '2.1', NULL)
      ,(5, '2.1', '2.1', 4)
      ,(6, '2.2', '2.2', 4)
      ,(7, '2.1.3', '2.1.3', 5);


WITH DataSource ([ID], [HierarchyLevel]) AS
(
    SELECT [ID]
          ,CAST(REPLACE('/' + [Name] + '/', '.', '/') AS HIERARCHYID)
    FROM @DataSource
)
DELETE @DataSource
FROM @DataSource DS
INNER JOIN DataSource DS1
    ON DS.[ID] = DS1.[ID]
WHERE [HierarchyLevel].IsDescendantOf('/2/1/') = 1;

SELECT *
FROM @DataSource;

答案 1 :(得分:2)

这可以使用递归公用表表达式完成。

要获得一个节点的所有孩子,您可以使用:

with tree as (
  select id, parent
  from eyalewin
  where id = 1
  union all
  select c.id, c.parent
  from eyalewin c
    join tree p on p.id = c.parent
)
select *
from tree;

然后可以用它来删除所有这些:

with tree as (
  select id, parent
  from eyalewin
  where id = 1
  union all
  select c.id, c.parent
  from eyalewin c
    join tree p on p.id = c.parent
)
delete from eyalewin
where id in (select id 
             from tree);