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

How to delete all nodes of given root in sql adjacency list

有这个table:

我要删除根节点,发送查询ID=1 并且我希望这个id的所有子节点也将被删除。

我该怎么做?

假设您有以下数据:

并且您想删除记录 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;

基本上,我们将您的记录转换为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;

这可以使用递归通用 table 表达式来完成。

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

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);