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

SELECT FOR XML AUTO a vrátit datové typy

FOR XML byl představen v SQL Server 2000.

SQL Server 2000 neměl MAX datové typy nebo XML datový typ. Nebylo také možné použít FOR XML v dílčím dotazu.

Článek Co vrací server FOR XML? vysvětluje

V SQL Server 2000 ... FOR XML ... byl implementován ve vrstvě kódu mezi dotazovacím procesorem a vrstvou přenosu dat ... dotazovací procesor vytváří výsledek stejným způsobem jako bezFOR XML a poté FOR XML kód formátuje sadu řádků jako XML. Pro maximální publikační výkonXML FOR XML provádí steaming XML formátování výsledné sady řádků a přímo posílá svůj výstup na server TDScode v malých kouscích bez ukládání celého XML do vyrovnávací paměti v prostoru serveru. Velikost chunku je 2033 UCS-2 znaků. XML větší než 2033UCS-2 znaků je tedy odesláno na stranu klienta ve více řádcích, z nichž každý obsahuje část XML. SQL Server používá pro tuto sadu řádků předdefinovaný název sloupce s jedním sloupcem typu NTEXT -“XML_F52E2B61-18A1-11d1-B105-00805F49916B ” – pro označení blokové sady XMLrowset v kódování UTF-16.

Zdá se tedy, že toto je stále implementováno stejným způsobem pro nejvyšší úroveň FOR XML i v pozdějších verzích.

SQL Server 2005 zavedl možnost používat FOR XML v dílčích dotazech (což znamená, že tyto nyní musí být zpracovávány procesorem dotazů, nikoli vrstvou mimo něj při streamování výsledků klientovi)

Stejný článek vysvětluje, že budou zadány jako NVARCHAR(MAX) nebo XML závisí na přítomnosti či nepřítomnosti type směrnice.

Stejně jako rozdíl mezi datovými typy to znamená další SELECT wrapper může způsobit drastický rozdíl ve výkonu, pokud #tab je velký.

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

Je možné vidět různé přístupy v zásobníkech volání a také v plánech provádění.

Přímo streamováno

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    

S dílčím dotazem

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 nakonec volají stejný základní kód XML, ale „nezabalená“ verze nemá v plánu samotném žádné iterátory XML, výsledku je dosaženo nahrazením volání metody z CXStmtSelect pomocí CXStmtXMLSelect místo toho (v plánu reprezentován jako kořenový uzel XML Select spíše než prostý starý uzel Select).

Na SQL Server 2016 CTP3 stále vidím ntext pro nejvyšší úroveň FOR XML . Nejvyšší úroveň však FOR JSON zobrazí se jako nvarchar(max)

Alespoň v CTP název speciálního sloupce JSON stále obsahuje GUID F52E2B61-18A1-11d1-B105-00805F49916B navzdory skutečnosti, že původem tohoto je rozhraní IXMLDocument.

Plány vypadají téměř stejně, ačkoli XML Select je nahrazen JSON Select

BTW:Na sestavení Microsoft SQL Server 2014 - 12.0.4213.0 (X64) Nevidím žádný rozdíl v chování mezi dočasnými tabulkami a trvalými tabulkami. To je pravděpodobně způsobeno jinou @@Version mezi prostředími, která vaše otázka používá http://sqlfiddle.com/ (12.0.2000.8) a https://data.stackexchange.com/ (12.0.4213.0).

Možná byla opravena chyba v sys.dm_exec_describe_first_result_set mezi dvěma stavbami z roku 2014.

V roce 2012 dostanu stejné výsledky jako Shnugo na 11.0.5343.0 (s NULL v prvních třech řádcích), ale po instalaci SP3 11.0.6020.0 dostanu stejné výsledky jako vaše počáteční výsledky zobrazené v otázce.



  1. Získejte poslední den v měsíci v PostgreSQL

  2. 3 způsoby, jak získat název dne z data v MariaDB

  3. Dotazování více databází najednou

  4. Funkce NLS_LOWER() v Oracle