8

我没有太多使用 HierarchyID,所以我有点不确定。如果我的表有 HierarchyID,如何执行级联删除?(即删除“父”时删除所有“子”)

我假设我必须使用 CTE 和 HierarchyID 函数,但不知道如何去做......

4

2 回答 2

6

基于触发器的解决方案是:

CREATE TRIGGER tr_Hierarchy_DeleteChildren
ON Hierarchy
FOR DELETE
AS
    DELETE FROM Hierarchy
    WHERE ID IN
    (
        SELECT DISTINCT h.ID
        FROM deleted d
        INNER JOIN Hierarchy h
        ON h.ObjectNode.IsDescendantOf(d.ObjectNode) = 1
      EXCEPT
        SELECT ID
        FROM deleted
    )

EXCEPT确保我们不会陷入无限递归循环。在我自己的实现中,我实际上在触发器正在运行的上下文信息中设置了一个标志,然后在触发器开始时检查此标志,如果该标志已设置,则提前返回。这不是必需的,但性能稍好一些。

或者,如果您不想使用触发器,则可以将以下逻辑放入存储过程中:

CREATE PROCEDURE DeleteHierarchyTree
    @ParentID hierarchyid
AS
DELETE FROM Hierarchy
WHERE ID.IsDescendantOf(@ParentID) = 1

It seems a lot simpler at first, but keep in mind that people have to remember to use this. If you don't have the trigger, and somebody does a direct DELETE on the hierarchy table instead of going through the SP, it could very easily orphan your child records without anyone knowing until it's too late.

于 2010-01-18T20:34:28.417 回答
4

你会想看看 T-SQL 中的 IsDescendantOf 方法。像这样的东西:

DECLARE @ParentNodeHID hierarchyid SET @ParentNodeHID = [您要开始删除的节点]

DELETE HierarchyTable WHERE NodeHID.IsDescendantOf(@ParentNodeHID) = 1

(HierarchyTable = 存储您的层次结构的表)

** 请记住,使用此方法时,节点被视为其自身的子节点。因此,无论您传递到 @ParentNodeHID 中的任何内容都将满足 WHERE 子句条件。

看看 BOL 文章:ms-help://MS.SQLCC.v10/MS.SQLSVR.v10.en/s10de_6tsql/html/edc80444-b697-410f-9419-0f63c9b5618d.htm

于 2009-10-12T12:25:33.233 回答