FOR XML
diperkenalkan di SQL Server 2000.
SQL Server 2000 tidak memiliki MAX
tipe data atau XML
tipe data. Juga tidak mungkin menggunakan FOR XML
dalam subkueri.
Artikel Apa yang dikembalikan sisi server UNTUK XML? menjelaskan
Di SQL Server 2000 ...
FOR XML
... diimplementasikan pada lapisan kode antara pemroses kueri dan lapisan pengangkutan data ... pemroses kueri menghasilkan hasil dengan cara yang sama seperti tanpaFOR XML
laluFOR XML
kode memformat rowset sebagai XML. Untuk kinerja penerbitan XML maksimumFOR XML
tidak mengukus format XML dari rowset yang dihasilkan dan langsung mengirimkan outputnya ke sisi server TDScode dalam potongan kecil tanpa buffering seluruh XML di ruang server. Ukuran potongan adalah 2033 karakter UCS-2. Dengan demikian, XML yang lebih besar dari 2033UCS-2 karakter dikirim ke sisi klien dalam beberapa baris yang masing-masing berisi sepotong XML. SQL Server menggunakan nama kolom yang telah ditentukan sebelumnya untuk baris ini dengan satu kolom jenisNTEXT
-“XML_F52E2B61-18A1-11d1-B105-00805F49916B
” – untuk menunjukkan XMLrowset yang dipotong dalam penyandian UTF-16.
Jadi tampaknya ini masih diterapkan dengan cara yang sama untuk FOR XML
tingkat atas di versi yang lebih baru juga.
SQL Server 2005 memperkenalkan kemampuan untuk menggunakan FOR XML
dalam subkueri (artinya ini sekarang perlu ditangani oleh pemroses kueri alih-alih lapisan di luarnya saat mengalirkan hasilnya ke klien)
Artikel yang sama menjelaskan bahwa ini akan diketik sebagai NVARCHAR(MAX)
atau XML
tergantung pada ada atau tidaknya type
arahan.
Selain perbedaan tipe data, ini berarti tambahan SELECT
wrapper dapat membuat perbedaan kinerja yang drastis jika #tab
besar.
/*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
Dimungkinkan untuk melihat pendekatan yang berbeda dalam tumpukan panggilan serta rencana eksekusi.
Distreaming langsung
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
Dengan subkueri
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
Keduanya akhirnya memanggil kode XML dasar yang sama tetapi versi "terbuka" tidak memiliki iterator XML dalam rencana itu sendiri, hasilnya dicapai dengan mengganti panggilan metode dari CXStmtSelect
dengan CXStmtXMLSelect
sebagai gantinya (diwakili dalam rencana sebagai node root Pilih XML daripada Select lama biasa).
Di SQL Server 2016 CTP3 saya masih melihat ntext
untuk FOR XML
tingkat atas . Namun FOR JSON
tingkat atas muncul sebagai nvarchar(max)
Setidaknya di CTP nama kolom khusus JSON masih berisi GUID F52E2B61-18A1-11d1-B105-00805F49916B
terlepas dari kenyataan bahwa asal mula ini adalah Antarmuka IXMLDocument.
Paket terlihat hampir sama meskipun XML Select diganti dengan JSON Select
BTW:Di build Microsoft SQL Server 2014 - 12.0.4213.0 (X64)
Saya tidak melihat perbedaan perilaku antara tabel temp dan tabel permanen. Ini mungkin karena @@Version
yang berbeda antara lingkungan pertanyaan Anda menggunakan http://sqlfiddle.com/ (12.0.2000.8) dan https://data.stackexchange.com/ (12.0.4213.0).
Mungkin bug telah diperbaiki di sys.dm_exec_describe_first_result_set
antara dua tahun 2014.
Pada 2012 saya mendapatkan hasil yang sama dengan Shnugo pada 11.0.5343.0 (dengan NULL
di tiga baris pertama) tetapi setelah menginstal SP3 11.0.6020.0 saya mendapatkan hasil yang sama dengan hasil awal Anda yang ditunjukkan pada pertanyaan.