Frage an XML-Ausgabe für hierarchische Daten mit FOR XML PATH in SQL Server zu erhalten
-
27-09-2019 - |
Frage
Ich habe eine Tabelle mit Spalten NodeId, NodeName, ParentNodeID und ich möchte in Form von XML wie folgt unter Verwendung von SQL-Abfrage gesamten Tabellendaten ouput. Ich denke, FOR XML PATH-Modus in SQL Server verwendet werden kann, um dies zu erreichen (ich benutze SQL Server 2008) Rekursion, aber nicht sicher, wie. Vielen Dank im Voraus
<?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>
Lösung
Ich löste es eine gespeicherte Prozedur und eine rekursive Funktion. Code unten. (Eigentlich wollte ich das ein Menü xml erzeugen, so dass der Code für das Menü angezeigt wird.
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
Andere Tipps
Diese Abfrage wird es tun - aber es ist nicht sehr sauber, dass man auf „manuell“ die Verschachtelung definieren und es wird nicht nur automatisch auf mehreren Ebenen skaliert tief ....
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')
Die Ausgabe ist:
<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>
Ich habe gehofft, es wäre ein Weg, dies zu tun mit einem rekursiven CTE (Common Table Expression), aber das hat nicht funktioniert: - (