T-SQL hierarchy - 使用查询获取面包屑
T-SQL hierarchy - get breadcrumbs using query
我在数据库中保存了虚拟文件夹结构,我想将面包屑从当前文件夹获取到根目录。数据可以不排序(但更好的是排序),我只想要当前文件夹的父文件夹。
table定义是:
DECLARE Folders TABLE (
FOL_PK INT IDENTITY(1,1) NOT NULL,
FOL_Name VARCHAR(200) NOT NULL,
FOL_FOL_FK INT NULL -- Foreign key to parent
)
这是我的解决方案:
DECLARE @FOL_PK INT = 5 -- Current folder PK
DECLARE @breadcrumbs TABLE (
FOL_PK INT NOT NULL,
FOL_Name VARCHAR(200) NOT NULL,
FOL_FOL_FK INT NULL
)
DECLARE @isRoot BIT = 0
,@currentFolderPK INT
,@parentFK INT
-- Get current and parent folder PK
SELECT
@currentFolderPK = FOL_PK
FROM
Folder
WHERE
FOL_PK = @FOL_PK
-- Breadcrumb
WHILE (@isRoot = 0)
BEGIN
-- Save to breadcrumb
INSERT INTO @breadcrumbs
SELECT
FOL_PK,
FOL_Name,
FOL_FOL_FK
FROM
Folder
WHERE
FOL_PK = @currentFolderPK
-- Set parent as current
SET @currentFolderPK =
(
SELECT
FOL_FOL_FK
FROM
Folder
WHERE
FOL_PK = @currentFolderPK
)
-- Set flag for loop
SET @isRoot = CASE
WHEN ISNULL(@currentFolderPK, 0) = 0 THEN 1
ELSE 0
END
END
-- Return breadcrumbs
SELECT
FOL_PK AS PK,
FOL_Name AS Name,
FOL_FOL_FK AS ParentFK
FROM
@breadcrumbs
问题是我对这个循环不太满意table。有没有其他复杂的解决方案如何做到这一点?
尝试使用递归通用Table表达式 (CTE):
MS SQL Server 2008 架构设置:
CREATE TABLE [Folders](
[FOL_PK] [int] IDENTITY(1,1) NOT NULL,
[FOL_Name] [varchar](200) NOT NULL,
[FOL_FOL_FK] [int] NULL,
CONSTRAINT [PK__Folders__FOL_PK] PRIMARY KEY CLUSTERED
(
[FOL_PK] ASC
))
ALTER TABLE [dbo].[Folders]
WITH CHECK ADD CONSTRAINT [FK_Folders_Folders] FOREIGN KEY([FOL_FOL_FK])
REFERENCES [dbo].[Folders] ([FOL_PK])
ALTER TABLE [dbo].[Folders] CHECK CONSTRAINT [FK_Folders_Folders]
INSERT INTO Folders(FOL_Name, FOL_FOL_FK)
VALUES ('Level 1', NULL),
('Level 1.1', 1),
('Level 1.2', 1),
('Level 1.3', 1),
('Level 1.2.1', 3),
('Level 1.2.2', 3),
('Level 1.2.3', 3),
('Level 1.2.2.1', 6),
('Level 1.2.2.2', 6),
('Level 1.2.2.3', 6),
('Level 1.3.1', 4),
('Level 1.3.2', 4)
查询 1:
DECLARE @FolderId Int = 9
;WITH CTE
AS
(
SELECT FOL_PK AS PK, FOL_NAME As Name, FOL_FOL_FK AS ParentFK
FROM Folders
WHERE FOL_PK = @FolderId
UNION ALL
SELECT F.FOL_PK AS PK, F.FOL_NAME AS Name, F.FOL_FOL_FK AS ParentFK
FROM Folders F
INNER JOIN CTE C
ON C.ParentFK = F.FOL_PK
)
SELECT *
FROM CTE
| PK | Name | ParentFK |
|----|---------------|----------|
| 9 | Level 1.2.2.2 | 6 |
| 6 | Level 1.2.2 | 3 |
| 3 | Level 1.2 | 1 |
| 1 | Level 1 | (null) |
我在数据库中保存了虚拟文件夹结构,我想将面包屑从当前文件夹获取到根目录。数据可以不排序(但更好的是排序),我只想要当前文件夹的父文件夹。
table定义是:
DECLARE Folders TABLE (
FOL_PK INT IDENTITY(1,1) NOT NULL,
FOL_Name VARCHAR(200) NOT NULL,
FOL_FOL_FK INT NULL -- Foreign key to parent
)
这是我的解决方案:
DECLARE @FOL_PK INT = 5 -- Current folder PK
DECLARE @breadcrumbs TABLE (
FOL_PK INT NOT NULL,
FOL_Name VARCHAR(200) NOT NULL,
FOL_FOL_FK INT NULL
)
DECLARE @isRoot BIT = 0
,@currentFolderPK INT
,@parentFK INT
-- Get current and parent folder PK
SELECT
@currentFolderPK = FOL_PK
FROM
Folder
WHERE
FOL_PK = @FOL_PK
-- Breadcrumb
WHILE (@isRoot = 0)
BEGIN
-- Save to breadcrumb
INSERT INTO @breadcrumbs
SELECT
FOL_PK,
FOL_Name,
FOL_FOL_FK
FROM
Folder
WHERE
FOL_PK = @currentFolderPK
-- Set parent as current
SET @currentFolderPK =
(
SELECT
FOL_FOL_FK
FROM
Folder
WHERE
FOL_PK = @currentFolderPK
)
-- Set flag for loop
SET @isRoot = CASE
WHEN ISNULL(@currentFolderPK, 0) = 0 THEN 1
ELSE 0
END
END
-- Return breadcrumbs
SELECT
FOL_PK AS PK,
FOL_Name AS Name,
FOL_FOL_FK AS ParentFK
FROM
@breadcrumbs
问题是我对这个循环不太满意table。有没有其他复杂的解决方案如何做到这一点?
尝试使用递归通用Table表达式 (CTE):
MS SQL Server 2008 架构设置:
CREATE TABLE [Folders](
[FOL_PK] [int] IDENTITY(1,1) NOT NULL,
[FOL_Name] [varchar](200) NOT NULL,
[FOL_FOL_FK] [int] NULL,
CONSTRAINT [PK__Folders__FOL_PK] PRIMARY KEY CLUSTERED
(
[FOL_PK] ASC
))
ALTER TABLE [dbo].[Folders]
WITH CHECK ADD CONSTRAINT [FK_Folders_Folders] FOREIGN KEY([FOL_FOL_FK])
REFERENCES [dbo].[Folders] ([FOL_PK])
ALTER TABLE [dbo].[Folders] CHECK CONSTRAINT [FK_Folders_Folders]
INSERT INTO Folders(FOL_Name, FOL_FOL_FK)
VALUES ('Level 1', NULL),
('Level 1.1', 1),
('Level 1.2', 1),
('Level 1.3', 1),
('Level 1.2.1', 3),
('Level 1.2.2', 3),
('Level 1.2.3', 3),
('Level 1.2.2.1', 6),
('Level 1.2.2.2', 6),
('Level 1.2.2.3', 6),
('Level 1.3.1', 4),
('Level 1.3.2', 4)
查询 1:
DECLARE @FolderId Int = 9
;WITH CTE
AS
(
SELECT FOL_PK AS PK, FOL_NAME As Name, FOL_FOL_FK AS ParentFK
FROM Folders
WHERE FOL_PK = @FolderId
UNION ALL
SELECT F.FOL_PK AS PK, F.FOL_NAME AS Name, F.FOL_FOL_FK AS ParentFK
FROM Folders F
INNER JOIN CTE C
ON C.ParentFK = F.FOL_PK
)
SELECT *
FROM CTE
| PK | Name | ParentFK |
|----|---------------|----------|
| 9 | Level 1.2.2.2 | 6 |
| 6 | Level 1.2.2 | 3 |
| 3 | Level 1.2 | 1 |
| 1 | Level 1 | (null) |