首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL Server 自動維護路徑的無限級分類表設計

     編輯:關於SqlServer

問題背景

傳統無限級分類表僅含 Id, ParentId, Name 三欄,查詢某節點所有子孫需遞迴或多次查詢,效能低且程式複雜。解決方案:新增路徑欄位,記錄從根節點到當前節點的完整路徑,查詢子孫變為簡單的 LIKE 'path/%' 操作。

表結構設計

CREATE TABLE [Sort] (
    [Id] INT PRIMARY KEY,
    [ParentId] INT NULL,
    [Name] NVARCHAR(500),
    [IdPath] VARCHAR(500),   -- 如 '/1/3/7/'
    [NamePath] NVARCHAR(500) -- 如 '/根目錄/子目錄/孫目錄/'
);

核心邏輯:存儲過程自動維護路徑

建立 SetSortPath 存儲過程,接受 @Id 參數,向上遞迴父節點構建路徑:

CREATE PROCEDURE [dbo].[SetSortPath]
    @Id INT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @PId VARCHAR(10), @ParentId INT, @Name NVARCHAR(500);
    DECLARE @IdPath VARCHAR(500) = '/', @NamePath NVARCHAR(500) = '/';

    SELECT @PId = [ParentId] FROM [Sort] WHERE [Id] = @Id;

    WHILE (@PId IS NOT NULL)
    BEGIN
        SELECT @ParentId = [ParentId], @Name = [Name] FROM [Sort] WHERE [Id] = @PId;
        SET @IdPath = '/' + @PId + @IdPath;
        SET @NamePath = '/' + @Name + @NamePath;
        IF (@ParentId <> @PId) SET @PId = @ParentId;
        ELSE SET @PId = NULL; -- 防止循環引用
    END

    IF (@IdPath = '/')
        UPDATE [Sort] SET [IdPath] = NULL, [NamePath] = NULL WHERE [Id] = @Id;
    ELSE
        UPDATE [Sort] SET [IdPath] = @IdPath, [NamePath] = @NamePath WHERE [Id] = @Id;
END

觸發器自動化

在 Sort 表上建立 INSERT, UPDATE, DELETE 觸發器,呼叫 SetSortPath:

  • 新增/修改節點時,更新該節點及其所有後代路徑。
  • 刪除節點時,清理相關路徑或標記失效。

查詢範例

-- 取得 Id=3 節點的所有子孫
SELECT * FROM [Sort] WHERE [IdPath] LIKE '/3/%';

-- 取得完整路徑顯示
SELECT [NamePath] FROM [Sort] WHERE [Id] = 7;
-- 結果: /根目錄/子目錄/孫目錄/

優缺點權衡

優點缺點
查詢子孫極快,無需遞迴修改節點需更新所有後代路徑,寫入開銷大
路徑資訊直觀,易於報表顯示路徑長度有限制,極深層級可能截斷
支援名稱路徑與 ID 路徑雙重查詢需透過觸發器/存儲過程確保資料一致性

結語

路徑枚舉模式適合「讀多寫少」的分類場景。若寫入頻繁,可考慮 Closure Table(關係閉包表)或遞迴 CTE 方案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved