我在数据库中有一个邻接列表,并希望通过 SQL SP 将 XML 格式的数据传递给客户端。我正在尝试使用 CTE 和 FOR XML,但我没有让 XML 节点嵌套。
仅供参考,这将代表一个站点地图。
表结构:
CREATE TABLE [dbo].[PageHierarchy](
[ModuleId] [int] NOT NULL,
[PageId] [int] IDENTITY(1,1) NOT NULL,
[ParentPageId] [int] NULL,
[PageUrl] [nvarchar](100) NULL,
[PageTitle] [nvarchar](50) NOT NULL,
[PageOrder] [int] NULL)
以及 CTE 的开始:
;WITH cte AS
(
select * from PageHierarchy where ParentPageId is null
union all
select child.* from PageHierarchy child inner join cte parent on parent.PageId = child.ParentPageId
)
SELECT ModuleId, PageId, ParentPageId, PageUrl, PageTitle, PageOrder FROM cte
group by ModuleId, PageId, ParentPageId, PageUrl, PageTitle, PageOrder
order by PageOrder
for xml auto, root ('bob')
生成如下所示的 XML:
<bob>
<cte ModuleId="1" PageId="1" PageUrl="~/Admin/" PageTitle="Administration" PageOrder="1000" />
<cte ModuleId="1" PageId="4" ParentPageId="1" PageTitle="Manage Users" PageOrder="1030" />
<cte ModuleId="1" PageId="5" ParentPageId="4" PageUrl="~/Admin/AddUser" PageTitle="Add Users" PageOrder="1040" />
<cte ModuleId="1" PageId="8" ParentPageId="4" PageUrl="~/Admin/EditUser" PageTitle="Edit/Search User" PageOrder="1070" />
</bob>
当我想要的是看起来像这样的 XML 时:
<bob>
<cte ModuleId="1" PageId="1" PageUrl="~/Admin/" PageTitle="Administration" PageOrder="1000" />
<cte ModuleId="1" PageId="4" ParentPageId="1" PageTitle="Manage Users" PageOrder="1030" >
<cte ModuleId="1" PageId="5" ParentPageId="4" PageUrl="~/Admin/AddUser" PageTitle="Add Users" PageOrder="1040" />
<cte ModuleId="1" PageId="8" ParentPageId="4" PageUrl="~/Admin/EditUser" PageTitle="Edit/Search User" PageOrder="1070" />
</cte>
</bob>
我猜问题不在于 CTE,而在于 select,但我不知道从哪里开始修复它。另外,我不知道嵌套有多深,所以我假设我需要它来支持至少 10 层深度。
编辑1:
我想我越来越近了......在查看此页面时,我创建了一个UDF,但仍然存在一些问题:
CREATE FUNCTION PageHierarchyNode(@PageId int)
RETURNS XML
WITH RETURNS NULL ON NULL INPUT
BEGIN RETURN
(SELECT ModuleId AS "@ModuleId", PageId AS "@PageId",
ParentPageId AS "@ParentPageId", PageUrl AS "@PageUrl",
PageTitle AS "@PageTitle", PageOrder AS "@PageOrder",
CASE WHEN ParentPageId=@PageId
THEN dbo.PageHierarchyNode(PageId)
END
FROM dbo.PageHierarchy WHERE ParentPageId=@PageId
FOR XML PATH('Page'), TYPE)
END
以及调用 UDF 的 SQL
SELECT ModuleId AS "@ModuleId", PageId AS "@PageId",
ParentPageId AS "@ParentPageId", PageUrl AS "@PageUrl",
PageTitle AS "@PageTitle", PageOrder AS "@PageOrder",
dbo.PageHierarchyNode(PageId)
FROM PageHierarchy
FOR XML PATH('Page'), ROOT('SiteMap'), TYPE
这将为我嵌套 XML,但它正在复制节点,这不是我想要的..
编辑2:
我只需要在调用 UDF 的 SELECT 中添加一个 WHERE 子句:
...
WHERE ParentPageId IS NULL