Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Wie entferne ich redundanten Namespace in einer verschachtelten Abfrage, wenn ich FOR XML PATH verwende

Nach Stunden der Verzweiflung und Hunderten von Versuchen und Irrtümern bin ich auf die folgende Lösung gekommen.

Ich hatte das gleiche Problem, als ich nur einen wollte xmlns -Attribut im Stamm Knoten nur . Aber ich hatte auch eine sehr schwierige Abfrage mit vielen Unterabfragen und FOR XML EXPLICIT Methode allein war einfach zu umständlich. Also ja, ich wollte den Komfort von FOR XML PATH in den Unterabfragen und auch um meine eigenen xmlns zu setzen .

Ich habe mir freundlicherweise den Code von 8kb ausgeliehen Antwort, weil es so schön war. Ich habe es zum besseren Verständnis etwas angepasst. Hier ist der Code:

DECLARE @Order TABLE (OrderID INT, OrderDate DATETIME)    
DECLARE @OrderDetail TABLE (OrderID INT, ItemID VARCHAR(1), Name VARCHAR(50), Qty INT)    
INSERT @Order VALUES (1, '2010-01-01'), (2, '2010-01-02')    
INSERT @OrderDetail VALUES (1, 'A', 'Drink',  5),
                           (1, 'B', 'Cup',    2),
                           (2, 'A', 'Drink',  2),
                           (2, 'C', 'Straw',  1),
                           (2, 'D', 'Napkin', 1)

-- Your ordinary FOR XML PATH query
DECLARE @xml XML = (SELECT OrderID AS "@OrderID",
                        (SELECT ItemID AS "@ItemID", 
                                Name AS "data()" 
                         FROM @OrderDetail 
                         WHERE OrderID = o.OrderID 
                         FOR XML PATH ('Item'), TYPE)
                    FROM @Order o 
                    FOR XML PATH ('Order'), ROOT('dummyTag'), TYPE)

-- Magic happens here!       
SELECT 1 AS Tag
      ,NULL AS Parent
      ,@xml AS [xml!1!!xmltext]
      ,'http://test.com/order' AS [xml!1!xmlns]
FOR XML EXPLICIT

Ergebnis:

<xml xmlns="http://test.com/order">
  <Order OrderID="1">
    <Item ItemID="A">Drink</Item>
    <Item ItemID="B">Cup</Item>
  </Order>
  <Order OrderID="2">
    <Item ItemID="A">Drink</Item>
    <Item ItemID="C">Straw</Item>
    <Item ItemID="D">Napkin</Item>
  </Order>
</xml>

Wenn Sie @xml ausgewählt haben allein würden Sie sehen, dass es den Root-Knoten dummyTag enthält . Wir brauchen es nicht, also entfernen wir es mit der Direktive xmltext in FOR XML EXPLICIT Abfrage:

,@xml AS [xml!1!!xmltext]

Die Erklärung in MSDN klingt zwar anspruchsvoller, aber praktisch weist sie den Parser an, die Inhalte auszuwählen von XML Root-Knoten.

Ich bin mir nicht sicher, wie schnell die Abfrage ist, aber derzeit entspanne ich mich und trinke Scotch wie ein Gentleman, während ich friedlich auf den Code schaue ...