如何删除自引用表中的树?

时间:2013-04-11 20:27:51

标签: sql-server self-join

我有下表:

MyTree(IDNode, IDRootNode, IDParentNode, Left, Right, Depth, ...)

IDNode是识别节点的主键。 IDRootNode是根节点。 IDParentNode是节点的父节点。 左和右是节点的位置。对于删除并不重要。

我看到以下代码是一个触发器,它允许从自引用表中删除寄存器:

CREATE TRIGGER MyTable_OnDelete ON MyTable
INSTEAD OF DELETE
AS 
BEGIN

  SET NOCOUNT ON;

  DELETE FROM mt
  FROM   deleted AS D
  JOIN   MyTable AS mt
  ON     d.Id = mt.ParentId

  DELETE FROM mt
  FROM   deleted AS D
  JOIN   MyTable AS mt
  ON     d.Id = mt.Id

END

如果我没错,首先删除我要删除的节点的子节点,然后删除该节点。但是如果孩子有孩子,也会被删除或只删除节点的孩子而不是孩子的孩子?

然后用recrsive CTE怎么样?

感谢。

3 个答案:

答案 0 :(得分:2)

如果树中的每个节点都使用节点所属树的id填充了IDRootNode列,则可以使用以下SQL删除树:

DELETE MyTable WHERE IDRootNode = @RootNodeId

答案 1 :(得分:2)

您可以使用递归CTE这样做:

;WITH cte AS (
    SELECT  IDNode
    FROM    Deleted
    UNION ALL
    SELECT  IDNode
    FROM    MyTree t
            JOIN cte c ON t.IDParentNode = c.IDNode
) 
DELETE  t
FROM    MyTree t
        JOIN cte c ON t.IDNode = c.IDNode;

更好的是,使用HierarchyId(如果在SQL Server 2008上)!

答案 2 :(得分:0)

Necromancing。
这里热闹的解决方案。
对于那些有任何理智的人,你应该知道删除级联存在。

示例:

FOREIGN KEY (parent_id) 
REFERENCES table_name(id) ON DELETE CASCADE 

然后你可以这样做:

DELETE FROM table_name WHERE id = @root_id

它将自动将删除级联到树下 不需要层次结构或CTE,也不需要任何递归。