Query per ottenere output XML per i dati gerarchici utilizzando FOR XML PATH in SQL Server
-
27-09-2019 - |
Domanda
Ho una tabella con le colonne NodeId, NodeName, ParentNodeId e voglio ouput tutti i dati della tabella in forma di Xml come la seguente query SQL tramite. Credo che per la modalità PATH XML in SQL Server può essere utilizzato per ottenere questo (io uso di SQL Server 2008) utilizzando la ricorsione, ma non è sicuro di come. Grazie in anticipo
<?xml version="1.0" encoding="utf-8" ?>
<Nodes>
<Node Id="1" Name="node1">
<Node Id="11" Name="node11">
<Node Id="111" Name="node111" />
<Node Id="112" Name="node112" />
</Node>
</Node>
<Node Id="2" Name="node2">
<Node Id="21" Name="node21">
<Node Id="211" Name="node211" />
<Node Id="212" Name="node212" />
</Node>
</Node>
</Nodes>
Soluzione
I risolto utilizzando una stored procedure e una funzione ricorsiva. codice mostrato sotto. (In realtà Ho voluto questo per generare un xml menù, in modo che il codice viene mostrato per il menu.
CREATE PROCEDURE [dbo].[usp_GetMenu]
AS
BEGIN
SET NOCOUNT ON;
SELECT dbo.fnGetMenuItems(MenuId)
FROM dbo.Menu
WHERE ParentMenuId IS NULL
FOR XML PATH('MenuItems')
END
GO
CREATE FUNCTION [dbo].[fnGetMenuItems]
(
@MenuId int
)
RETURNS XML
WITH RETURNS NULL ON NULL INPUT
AS
BEGIN
RETURN
(
SELECT MenuId AS "@Id"
, [Name] AS "@Name"
, [URL] AS "@URL"
, [Key] AS "@Key"
, [dbo].[fnGetMenuItems](MenuId)
FROM dbo.Menu
WHERE ParentMenuId = @MenuId
FOR XML PATH('MenuItem'),TYPE
)
END
GO
Altri suggerimenti
Questa query lo farà - tuttavia, non è molto pulita in che si deve "manualmente" definire la nidificazione e non sarà solo in scala automaticamente a più livelli di profondità ....
SELECT
n.ID AS '@Id',
n.NAME AS '@Name',
(SELECT
n2.ID AS '@Id',
n2.NAME AS '@Name',
(SELECT
n3.ID AS '@Id',
n3.NAME AS '@Name'
FROM
dbo.Nodes n3
WHERE
n3.ParentNode = n2.ID
FOR XML PATH('Node'), TYPE
)
FROM
dbo.Nodes n2
WHERE
n2.ParentNode = n.ID
FOR XML PATH('Node'), TYPE
)
FROM
dbo.Nodes n
WHERE
n.ParentNode IS NULL
FOR XML PATH('Node'), ROOT('Nodes')
L'uscita è:
<Nodes>
<Node Id="1" Name="node1">
<Node Id="11" Name="node11">
<Node Id="111" Name="node111" />
<Node Id="112" Name="node112" />
</Node>
</Node>
<Node Id="2" Name="node2">
<Node Id="21" Name="node21">
<Node Id="211" Name="node211" />
<Node Id="212" Name="node212" />
</Node>
</Node>
</Nodes>
Speravo ci sarebbe un modo per fare questo con una CTE ricorsiva (Common Table Expression), ma che non ha funzionato: - (