Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Comment supprimer l'espace de noms redondant dans une requête imbriquée lors de l'utilisation de FOR XML PATH

Après des heures de désespoir et des centaines d'essais et d'erreurs, j'ai trouvé la solution ci-dessous.

J'ai eu le même problème, alors que je voulais un seul xmlns attribut, sur la racine nœud uniquement . Mais j'ai aussi eu une requête très difficile avec beaucoup de sous-requêtes et FOR XML EXPLICIT méthode seule était tout simplement trop lourde. Alors oui, je voulais la commodité de FOR XML PATH dans les sous-requêtes et aussi pour définir mon propre xmlns .

J'ai gentiment emprunté le code de 8kb réponse, parce que c'était si agréable. Je l'ai un peu modifié pour mieux comprendre. Voici le 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

Résultat :

<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>

Si vous avez sélectionné @xml seul, vous verriez qu'il contient le nœud racine dummyTag . Nous n'en avons pas besoin, nous le supprimons donc en utilisant la directive xmltext dans FOR XML EXPLICIT requête :

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

Bien que l'explication dans MSDN semble plus sophistiquée, mais en pratique, elle indique à l'analyseur de sélectionner le contenu de XML nœud racine.

Je ne sais pas à quelle vitesse la requête est rapide, mais actuellement je me détends et je bois du scotch comme un gentleman tout en regardant paisiblement le code...