Reputation: 11571
I have a tree table with column ID
, ParentID
and Hierarchy
and want to generate Hierarchy
column value dependent by ParentID
. for this purpose I use triggers. do exists better way to generate Hierarchy column value?
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
Function :
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 this table also have trigger to set Hierarchy column again when ParentID
Changed.
what's the best practices for this problem?
EDIT 1 : I look up solution that not use trigger if possible.
Upvotes: 9
Views: 2825
Reputation: 704
No need for cursor
just use
Insert Into MyTable (Name, ParentID, Hierarchy)
select Name, ParentID, dbo.F_MyTableGetHID(NULL, ParentID)
from inserted
Can you explain function - not sur what its doing. But looks like it could be turned into a query and therefore could be combined with above - best practice is always do set theory on relational databases
Upvotes: 0
Reputation: 5503
You can create a function that calculates the hierarchyid value, given the foreign-key to the parent. Then you can call this function as the default value calculator for the column. If you prevent the users from inserting into this column, the default value will always apply.
This solution will work, only if the parent-child relationship is not updatable.
Upvotes: 1
Reputation:
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
Upvotes: 1
Reputation: 6043
I have a different approach to answer both the questions. I generally avoid using triggers until it is the last choice as it adds un-necessary overhead on the database.
Comparision between triggers and stored procedure
Enough said, this is why I prefer stored procs. You can create a job file (say for ex : it executes after every 30 min, or any other time) via agent. You can use the logic for insertion in that job file. In this way your data in the tree table
would be near to real time.
now reference to create an agent :
http://msdn.microsoft.com/en-us/library/ms191128(v=sql.90).aspx
http://msdn.microsoft.com/en-us/library/ms181153(v=sql.105).aspx
Upvotes: 3
Reputation: 26753
You asked for the best practice.
The best practice is not to use the adjacency list model (which is what you have) and instead switch to the nested set model.
It's more difficult to code and understand, which is why it's not as popular, but it's much more flexible.
Upvotes: 1