sql >> Base de Datos >  >> RDS >> Sqlserver

¿Cómo elimino el espacio de nombres redundante en una consulta anidada cuando uso FOR XML PATH?

Después de horas de desesperación y cientos de pruebas y errores, encontré la solución a continuación.

Tuve el mismo problema, cuando quería solo uno xmlns atributo, en la raíz nodo solo . Pero también tuve una consulta muy difícil con muchas subconsultas y FOR XML EXPLICIT método solo era demasiado engorroso. Así que sí, quería la comodidad de FOR XML PATH en las subconsultas y también para configurar mis propios xmlns .

Amablemente tomé prestado el código de 8kb's respuesta, porque fue muy agradable. Lo modifiqué un poco para que se entendiera mejor. Aquí está el código:

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

Resultado:

<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 seleccionó @xml solo, vería que contiene el nodo raíz dummyTag . No lo necesitamos, así que lo eliminamos usando la directive xmltext en FOR XML EXPLICIT consulta:

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

Aunque la explicación en MSDN suena más sofisticada, prácticamente le dice al analizador que seleccione los contenidos de XML nodo raíz.

No estoy seguro de cuán rápida es la consulta, pero actualmente me estoy relajando y bebiendo whisky escocés como un caballero mientras miro tranquilamente el código...