9

我有一个带有列的树表IDParentID并且Hierarchy想要生成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

ParentID对于更新此表也有触发器在更改时再次设置层次结构列。

这个问题的最佳实践是什么?

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

4

5 回答 5

3

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

触发器和存储过程的比较

  • 在数据库中查看表关系、约束、索引、存储过程很容易,但很难查看触发器。
  • 触发器执行对客户端应用程序不可见。它们不可见或可以在调试代码中跟踪。
  • 很容易忘记触发器,如果​​没有文档,新开发人员将很难弄清楚它们的存在。
  • 每次更新数据库字段时都会运行触发器,这会增加系统开销。它使系统运行更慢。

说得够多了,这就是为什么我更喜欢存储过程。您可以通过代理创建一个作业文件(例如 ex :它每 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

于 2012-08-04T08:20:23.570 回答
1

您要求最佳实践。

最佳实践是不使用邻接列表模型(这是您所拥有的),而是切换到嵌套集模型。

它更难编码和理解,这就是它不那么受欢迎的原因,但它更灵活。

于 2012-08-03T10:15:07.047 回答
1

在这种情况下,您应该使用不带游标的触发器

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
于 2012-08-04T18:50:41.793 回答
1

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

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

于 2012-08-06T05:12:11.313 回答
0

不需要光标

只需使用

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

你能解释一下功能吗?不知道它在做什么。但看起来它可以变成一个查询,因此可以与上面结合起来——最佳实践总是在关系数据库上做集合论

于 2012-08-05T22:16:26.647 回答