sql >> Databáze >  >> RDS >> Sqlserver

Jak odstraním nadbytečný jmenný prostor ve vnořeném dotazu při použití FOR XML PATH

Po hodinách zoufalství a stovkách pokusů a omylů jsem přišel s níže uvedeným řešením.

Měl jsem stejný problém, když jsem chtěl jen jeden xmlns atribut v kořenovém adresáři pouze uzel . Ale měl jsem také velmi obtížný dotaz se spoustou poddotazů a FOR XML EXPLICIT samotná metoda byla příliš těžkopádná. Takže ano, chtěl jsem pohodlí FOR XML PATH v poddotazech a také nastavit vlastní xmlns .

Laskavě jsem si vypůjčil kód 8kb odpověď, protože to bylo tak hezké. Trochu jsem to upravil pro lepší pochopení. Zde je kód:

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

Výsledek:

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

Pokud jste vybrali @xml samotný, uvidíte, že obsahuje kořenový uzel dummyTag . Nepotřebujeme ji, proto ji odstraníme pomocí směrnice xmltext v FOR XML EXPLICIT dotaz:

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

Vysvětlení v MSDN sice zní sofistikovaněji, ale prakticky říká analyzátoru, aby vybral obsah XML kořenový uzel.

Nejsem si jistý, jak rychlý je dotaz, ale momentálně odpočívám a piju skotskou jako pán, zatímco si klidně prohlížím kód...



  1. php a html formulář na stejné stránce

  2. Pohodlný způsob, jak zabalit dlouhé příkazy SQL do javascriptu

  3. Rozdíl mezi TRIM() a TRIM_ORACLE() v MariaDB

  4. Má PHP konstrukci podobnou DataSetu .NET?