自动生成层次结构值

时间:2012-07-08 07:45:50

标签: sql sql-server sql-server-2008 sql-server-2008-r2

我有一个包含列IDParentIDHierarchy的树表,并希望生成Hierarchy列值依赖ParentID。为此,我使用触发器。是否存在生成层次结构列值的更好方法?

ALTER TRIGGER [TR_MyTable_BeforInsert] ON [MyTable]
INSTEAD OF INSERT
AS BEGIN
SET NOCOUNT ON;
Declare @Name NVarChar(100),
        @ParentID Int

Declare DACategory Cursor For
Select  A.Name, A.ParentID
From    Inserted A
OPEN    DACategory
FETCH NEXT FROM DACategory INTO @Name, @ParentID
While @@FETCH_STATUS=0 Begin

    Insert Into MyTable (Name, ParentID, Hierarchy)
    Values (@Name, @ParentID, dbo.F_MyTableGetHID(NULL, @ParentID))

    FETCH NEXT FROM DACategory INTO @Name, @ParentID
End
Close   DACategory
Deallocate DACategory
END

功能:

ALTER FUNCTION [F_MyTableGetHID]
(
    @ID int,
    @ParentID int
)
RETURNS HierarchyID

AS BEGIN
    Declare @RootHID HierarchyID, 
            @LastHID HierarchyID

    IF (@ParentID IS NULL)Begin
        Set @RootHID = HierarchyID::GetRoot()
        Select @LastHID = Max(Hierarchy) From MyTable Where ParentID IS NULL
    End Else Begin
        Select @RootHID = Hierarchy From MyTable Where ID = @ParentID
        select @LastHID = Max(Hierarchy) From MyTable where ParentID = @ParentID
    End
    return @RootHID.GetDescendant(@LastHID, NULL)
END

for Update此表还有触发器在ParentID更改时再次设置Hierarchy列。

此问题的最佳做法是什么?

编辑1 :如果可能,我查找不使用触发器的解决方案。

5 个答案:

答案 0 :(得分:2)

我有不同的方法来回答这两个问题。我通常会避免使用触发器,直到它成为最后一个选择,因为它会在数据库上添加不必要的开销。

触发器和存储过程之间的比较

  • 很容易查看表关系,约束,索引,存储 数据库中的过程很难查看触发器。
  • 触发器对客户端应用程序应用程序执行不可见。他们 在调试代码中不可见或可以跟踪。
  • 如果没有文档,很容易忘记触发器 很难为他们的新开发者找到答案 存在。
  • 每次更新数据库字段时都会触发触发器 是系统的开销。它使系统运行速度变慢。

够了,这就是为什么我更喜欢存储过程。您可以通过代理创建一个作业文件(比方说:它每隔30分钟或任何其他时间执行)。您可以使用该逻辑在该作业文件中插入。这样,tree table中的数据就会接近实时。

现在引用创建代理:
http://msdn.microsoft.com/en-us/library/ms191128(v=sql.90).aspx
http://msdn.microsoft.com/en-us/library/ms181153(v=sql.105).aspx

答案 1 :(得分:1)

你要求最好的做法。

最佳做法是不使用邻接列表模型(这是你拥有的),而是切换到嵌套集模型。

编码和理解起来比较困难,这就是为什么它不那么流行,但它更灵活。

答案 2 :(得分:1)

在此上下文中,您应该使用不带游标的Trigger

ALTER TRIGGER [TR_MyTable_BeforInsert] ON [MyTable]
INSTEAD OF INSERT
AS 
BEGIN
    SET NOCOUNT ON;
    Insert Into MyTable (Name, ParentID, Hierarchy)
    Select Name, ParentID, dbo.F_MyTableGetHID(NULL, ParentID)
    From inserted
END

答案 3 :(得分:1)

您可以创建一个函数来计算hierarchyid值,给定父键的外键。然后,您可以将此函数作为列的默认值计算器。如果阻止用户插入此列,则始终应用默认值。

只有当父子关系不可更新时,此解决方案才有效。

答案 4 :(得分:0)

无需光标

只需使用

Insert Into MyTable (Name, ParentID, Hierarchy) 
 select Name, ParentID, dbo.F_MyTableGetHID(NULL, ParentID)   
  from inserted

你能解释一下这个功能吗?但看起来它可以变成一个查询,因此可以与上面结合 - 最佳实践总是在关系数据库上设置理论