Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Jak usunąć nadmiarową przestrzeń nazw w zagnieżdżonej kwerendzie podczas korzystania z FOR XML PATH?

Po godzinach desperacji i setkach prób i błędów wymyśliłem poniższe rozwiązanie.

Miałem ten sam problem, kiedy chciałem tylko jeden xmlns atrybut, w głównym węzeł tylko . Ale miałem też bardzo trudne zapytanie z wieloma podzapytaniami i FOR XML EXPLICIT sama metoda była zbyt uciążliwa. Więc tak, chciałem wygody FOR XML PATH w podzapytaniach, a także ustawić własne xmlns .

Uprzejmie pożyczyłem kod 8kb odpowiedź, bo to było takie miłe. Poprawiłem to trochę, aby lepiej zrozumieć. Oto kod:

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

Wynik:

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

Jeśli wybrałeś @xml sam, zobaczysz, że zawiera węzeł główny dummyTag . Nie potrzebujemy go, więc usuwamy go za pomocą dyrektywy xmltext w FOR XML EXPLICIT zapytanie:

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

Chociaż wyjaśnienie w MSDN brzmi bardziej wyrafinowane, ale praktycznie mówi parserowi, aby wybrał zawartość z XML węzeł główny.

Nie jestem pewien, jak szybkie jest zapytanie, ale obecnie odpoczywam i piję szkocką jak dżentelmen, spokojnie patrząc na kod...



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Microsoft SQL Server 2005/2008:XML a typ danych tekst/varchar

  2. Rekurencyjne CTE z unikalnym identyfikatorem musi mieć wartość w zakotwiczeniu

  3. Użyj FILE_IDEX(), aby zwrócić identyfikator pliku bazy danych w SQL Server

  4. Plusy i minusy TRUNCATE vs DELETE FROM

  5. Zrozumienie instrukcji DROP TABLE w SQL Server