樹形結構數據的存儲


一、概述

樹形結構在國人中的需求很多,比如單位和子單位、人員的上下級管理關系等,一般數據庫設計是通過Id,Pid來確定父子關系,但如果要查詢某個節點下所有的子節點,可以通過with關鍵字查詢效,具體方法可見這篇文章,改進方法主要有兩種:物化路徑和左右節點。對於使用物化路徑,有通過存儲過程實現的,比如 ,最近在網上看了一片文章,主要是對物化路徑的方法進行改進,使用存儲過程自動修改物化路徑,文章可見,具體操作如下:

二、數據庫設計

CREATE TABLE [dbo].[Depts](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](50) NOT NULL,
    [FullPath] [nvarchar](50) NULL,
    [HierarchyLevel] [int] NULL,
    [Parent_Id] [int] NULL,
    [SortCode] [int] NULL,
)

主要是添加了兩個輔助列FullPath和HierarchyLevel,用於記錄的全路徑和層級。

三、存儲過程

2.1插入記錄觸發器

USE [PeopleManage]
GO
/****** Object:  Trigger [dbo].[trgDeptInsert]    Script Date: 2015/3/27 11:38:28 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[trgDeptInsert] ON [dbo].[Depts]  FOR INSERT
AS 
BEGIN
    DECLARE @numrows int
    SET @numrows = @@ROWCOUNT
    
    if @numrows > 1 
    BEGIN
        RAISERROR('Only single row insertion is supported', 16, 1)
        ROLLBACK TRAN
    END
    ELSE    
    BEGIN
        UPDATE 
            E
        SET
            HierarchyLevel    = 
            CASE 
                WHEN E.Parent_Id IS NULL THEN 0
                ELSE Parent.HierarchyLevel + 1
            END,
            FullPath = 
            CASE
                WHEN E.Parent_Id IS NULL THEN '.'
                ELSE Parent.FullPath 
            END + CAST(E.Id AS varchar(10)) + '.'
            FROM
                Depts AS E
            INNER JOIN
                inserted AS I ON I.Id = E.Id
            LEFT OUTER JOIN
                Depts AS Parent ON Parent.Id = E.Parent_Id
    END
END

2.2修改記錄觸發器

USE [PeopleManage]
GO
/****** Object:  Trigger [dbo].[trgDeptUpdate]    Script Date: 2015/3/27 11:39:48 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[trgDeptUpdate] ON [dbo].[Depts] FOR UPDATE
AS 
BEGIN
  IF @@ROWCOUNT = 0 
        RETURN
    
    if UPDATE(Parent_Id) 
    BEGIN
        UPDATE
            E
        SET
            HierarchyLevel    = 
                E.HierarchyLevel - I.HierarchyLevel + 
                    CASE 
                        WHEN I.Parent_Id IS NULL THEN 0
                        ELSE Parent.HierarchyLevel + 1
                    END,
            FullPath = 
                ISNULL(Parent.FullPath, '.') +
                CAST(I.Id as varchar(10)) + '.' +
                RIGHT(E.FullPath, len(E.FullPath) - len(I.FullPath))
            FROM
                Depts AS E
            INNER JOIN
                inserted AS I ON E.FullPath LIKE I.FullPath + '%'
            LEFT OUTER JOIN
                Depts AS Parent ON I.Parent_Id = Parent.Id
    END

END

四、使用方法

對於數據的增刪改,不需要理會FullPath和HierarchyLevel這兩列,觸發器會自動添加或者修改

如果要查詢某個節點下的所有節點,只需要使用Linke語句即可


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM