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

WYBIERZ DLA XML AUTO i zwróć typy danych

FOR XML został wprowadzony w SQL Server 2000.

SQL Server 2000 nie miał MAX typy danych lub XML typ danych. Nie było też możliwości użycia FOR XML w podzapytaniu.

Artykuł Co zwraca strona serwera FOR XML? wyjaśnia

W SQL Server 2000... FOR XML ... został zaimplementowany w warstwie kodu między procesorem zapytań a warstwą transportu danych ... procesor zapytań generuje wynik w taki sam sposób, jak bez FOR XML a następnie FOR XML kod formatuje zestaw wierszy jako XML. Dla maksymalnej wydajności publikowania XML FOR XML robi parowe formatowanie XML powstałego zestawu wierszy i bezpośrednio wysyła swoje dane wyjściowe do TDScode po stronie serwera w małych porcjach bez buforowania całego XML w przestrzeni serwera. Rozmiar porcji to 2033 znaków UCS-2. W ten sposób XML większy niż 2033UCS-2 znaków jest wysyłany po stronie klienta w wielu wierszach, z których każdy zawiera fragment kodu XML. SQL Server używa wstępnie zdefiniowanej nazwy kolumny dla tego zestawu wierszy z jedną kolumną typu NTEXT -„XML_F52E2B61-18A1-11d1-B105-00805F49916B ” – aby wskazać fragmentaryczny zestaw XMLrowset w kodowaniu UTF-16.

Wygląda więc na to, że jest to nadal zaimplementowane w ten sam sposób dla najwyższego poziomu FOR XML w późniejszych wersjach.

SQL Server 2005 wprowadził możliwość używania FOR XML w podzapytaniach (co oznacza, że ​​muszą one być teraz obsługiwane przez procesor zapytań, a nie przez warstwę poza nim podczas przesyłania wyników do klienta)

W tym samym artykule wyjaśniono, że zostaną one wpisane jako NVARCHAR(MAX) lub XML zależnie od obecności lub nie type dyrektywa.

Oprócz różnicy typów danych oznacza to dodatkowy SELECT wrapper może spowodować drastyczną różnicę w wydajności, jeśli #tab jest duży.

/*Can be streamed straight out to client without using server storage*/
SELECT col
FROM #tab
FOR XML AUTO

/*XML constructed in its entirety in tempdb first*/
SELECT(SELECT col
FROM #tab
FOR XML AUTO) AS wrapped_subquery

Można zobaczyć różne podejścia w stosach wywołań, a także w planach wykonania.

Przesyłane bezpośrednio

sqllang.dll!CXMLExecContext::AddTagAndAttributes()  + 0x5a9 bytes                   
sqllang.dll!CXMLExecContext::AddXMLRow()  + 0x2b7 bytes                 
sqltses.dll!CEsExec::FastMoveEval()  + 0x9c bytes                   
sqllang.dll!CXStmtQuery::ErsqExecuteQuery()  + 0x280 bytes                  
sqllang.dll!CXStmtXMLSelect::WrapExecute()  + 0x2d7 bytes                   
sqllang.dll!CXStmtXMLSelect::XretDoExecute()  + 0x355 bytes                 
sqllang.dll!CXStmtXMLSelect::XretExecute()  + 0x46 bytes                    
sqllang.dll!CMsqlExecContext::ExecuteStmts<1,1>()  + 0x368 bytes                    
sqllang.dll!CMsqlExecContext::FExecute()  + 0x6cb bytes                 
sqllang.dll!CSQLSource::Execute()  + 0x3ee bytes                    
sqllang.dll!process_request()  + 0x757 bytes    

Z zapytaniem podrzędnym

sqllang.dll!CXMLExecContext::AddTagAndAttributes()  + 0x5a9 bytes
sqllang.dll!CXMLExecContext::AddXMLRow()  + 0x2b7 bytes
sqllang.dll!CForXmlSerialize::ProcessRow()  + 0x19 bytes
sqllang.dll!CUDXR_Base::PushRow()  + 0x30 bytes
sqlmin.dll!CQScanUdx::Open()  + 0xd5 bytes
sqlmin.dll!CQueryScan::StartupQuery()  + 0x170 bytes
sqllang.dll!CXStmtQuery::SetupQueryScanAndExpression()  + 0x391 bytes
sqllang.dll!CXStmtQuery::InitForExecute()  + 0x34 bytes
sqllang.dll!CXStmtQuery::ErsqExecuteQuery()  + 0x217 bytes
sqllang.dll!CXStmtSelect::XretExecute()  + 0xed bytes
sqllang.dll!CMsqlExecContext::ExecuteStmts<1,1>()  + 0x368 bytes
sqllang.dll!CMsqlExecContext::FExecute()  + 0x6cb bytes
sqllang.dll!CSQLSource::Execute()  + 0x3ee bytes
sqllang.dll!process_request()  + 0x757 bytes

Oba kończą wywołanie tego samego bazowego kodu XML, ale wersja „nieopakowana” nie ma żadnych iteratorów XML w samym planie, wynik jest osiągany przez zastąpienie wywołań metod z CXStmtSelect z CXStmtXMLSelect zamiast tego (reprezentowany w planie jako węzeł główny XML Select zamiast zwykłego starego Select).

Na SQL Server 2016 CTP3 nadal widzę ntext dla najwyższego poziomu FOR XML . Jednak najwyższego poziomu FOR JSON pojawia się jako nvarchar(max)

Przynajmniej w CTP specjalna nazwa kolumny JSON nadal zawiera identyfikator GUID F52E2B61-18A1-11d1-B105-00805F49916B pomimo faktu, że źródłem tego jest interfejs IXMLDocument.

Plany wyglądają bardzo podobnie, chociaż XML Select został zastąpiony przez JSON Select

BTW:W kompilacji Microsoft SQL Server 2014 - 12.0.4213.0 (X64) Nie widzę żadnej różnicy w zachowaniu między tabelami tymczasowymi a tabelami stałymi. Jest to prawdopodobnie spowodowane różnymi @@Version między środowiskami, w których Twoje pytanie używa http://sqlfiddle.com/ (12.0.2000.8) i https://data.stackexchange.com/ (12.0.4213.0).

Może błąd został naprawiony w sys.dm_exec_describe_first_result_set między dwoma wersjami z 2014 roku.

W 2012 otrzymuję takie same wyniki jak Shnugo na 11.0.5343.0 (z NULL w pierwszych trzech wierszach), ale po zainstalowaniu dodatku SP3 11.0.6020.0 otrzymuję to samo, co początkowe wyniki pokazane w pytaniu.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak określić lokalizację plików danych i plików dziennika podczas tworzenia bazy danych w SQL Server

  2. Eksportuj dane z SQL Server do Excela i pliku tekstowego za pomocą pakietu SSIS

  3. Czy mogę użyć instrukcji CASE w warunku JOIN?

  4. Czy unikalny klucz serwera SQL jest również indeksem?

  5. jak skonfigurować plik konfiguracyjny hibernacji dla serwera sql?