sql-serverstored-procedureshierarchyhierarchical-data

Update hierarchy after deletion of row


I have a table that contains tree-like data (hierarchic design). Here is a small sample:

+----+----------+-----------+-------+----------+---------+
| ID | ParentID | Hierarchy | Order | FullPath | Project |
+----+----------+-----------+-------+----------+---------+
|  1 | null     |         1 |     1 | 1        |       1 |
|  2 | null     |         2 |     2 | 2        |       1 |
|  3 | 1        |       1.1 |     1 | 1-3      |       1 |
|  4 | 1        |       1.2 |     2 | 1-4      |       1 |
|  5 | 4        |     1.2.1 |     1 | 1-4-5    |       1 |
|  6 | 2        |       2.1 |     1 | 2-6      |       1 |
|  7 | null     |         3 |     1 | 1        |       2 |
+----+----------+-----------+-------+----------+---------+

Project indicates which project owns the hierarchic dataset ParentID is the ID of the parent node, it has a foreign key on ID. Order is the rank of the element in one branch. For example, IDs 1, 2 and 7 are on the same node while 3 and 4 are in another. FullPath shows the order using the ID (it's for system use and performance reasons).

Hierarchy is the column displayed to the user, which displays the hierarchy to the UI. It auto calculates after every insert, update and delete, and it's the one I'm having issues.

I created a procedure for deletion elements in the table. It receives as input the ID of the element to delete and deletes it, along with it's children if any. Then, it recalculates the FullPath and the Order Column .That works.

Problems is when I try to update the Hierarchy column. I use this procedure:

SELECT  T.ID,
        T.ParentID,
        CASE WHEN T.ParentID IS NOT NULL THEN 
            CONCAT(T1.Hierarchy, '.', CAST(T.Order AS NVARCHAR(255))) 
        ELSE 
            CAST(T.Order AS NVARCHAR(255))
        END AS Hierarchy
INTO    #tmp
FROM    t_HierarchyTable T
LEFT JOIN   t_HierarchyTable T1
        ON  T1.ID = T.ParentID
WHERE Project = @Project --Variable to only update the current project for performance
ORDER BY T.FullPath

--Update the table with ID as key on tmp table

This fails when I delete items that have lower order than others and they have children. For example, if I delete the item 3, item 4 Hierachy will be corrected (1.1), BUT its child won't (it will stay at 1.2.1, while it should be 1.1.1). I added the order by to make sure parents where updated first, but no change.

What is my error, I really don't know how to fix this.


Solution

  • I managed to update the hierarchy with a CTE. Since I have the order, I can append it to Hierarchy, based on the previous branch (parent) who is already updated.

    ;WITH CODES(ID, sCode, iLevel) AS 
    (
        SELECT 
            T.[ID]                                  AS [ID],
            CONVERT(VARCHAR(8000), T.[Order])       AS [Hierarchy],
            1                                       AS [iLevel]
        FROM 
            [dbo].[data] AS T
        WHERE 
            T.[ParentID] IS NULL
    
        UNION ALL
    
        SELECT 
            T.[ID]                                      AS [ID],
            P.[Hierarchy] + IIF(RIGHT(P.[Hierarchy], 1) <> '-', '-', '') + CONVERT(VARCHAR(8000), T.[Order])    AS [Hierarchy],
            P.[iLevel] + 1                              AS [iLevel]
        FROM 
            [dbo].[data] AS T
        INNER JOIN CODES AS P ON 
            P.[ID] = T.[ParentID]
        WHERE
            P.[iLevel] < 100
    )
    SELECT 
        [ID], [Hierarchy], [iLevel]
    INTO
        #CODES
    FROM 
        CODES