sql >> データベース >  >> RDS >> Sqlserver

SELECT FORXMLAUTOおよび戻りデータ型

    FOR XML SQLServer2000で導入されました。

    SQLServer2000にはMAXがありませんでした データ型またはXML データ・タイプ。 FOR XMLを使用することもできませんでした サブクエリで。

    記事サーバーサイドのFORXMLは何を返しますか?説明

    SQLServer2000の場合...FOR XML ...クエリプロセッサとデータトランスポート層の間のコード層に実装されました...クエリプロセッサは、FOR XMLがない場合と同じ方法で結果を生成します。 次に、FOR XML コードは行セットをXMLとしてフォーマットします。 XMLパブリッシングのパフォーマンスを最大化するためにFOR XML 結果の行セットのXMLフォーマットをスチーミングし、その出力をサーバースペースにXML全体をバッファリングせずに小さなチャンクでサーバー側のTDScodeに直接送信します。チャンクサイズは2033UCS-2文字です。したがって、2033UCS-2文字より大きいXMLは、それぞれがXMLのチャンクを含む複数の行でクライアント側に送信されます。 SQL Serverは、この行セットに事前定義された列名をタイプNTEXTの1つの列で使用します -「XML_F52E2B61-18A1-11d1-B105-00805F49916B 」–UTF-16エンコーディングでチャンク化されたXML行セットを示します。

    したがって、これはトップレベルのFOR XMLでも同じ方法で実装されているようです。 それ以降のバージョンでも。

    SQL Server 2005では、FOR XMLを使用する機能が導入されました。 サブクエリ内(つまり、結果をクライアントにストリーミングするときに、クエリプロセッサの外部のレイヤーではなく、クエリプロセッサで処理する必要があります)

    同じ記事で、これらはNVARCHAR(MAX)として入力されると説明されています またはXML typeの有無によって異なります ディレクティブ。

    データ型の違いだけでなく、これは追加のSELECTを意味します #tabの場合、ラッパーはパフォーマンスに大幅な違いをもたらす可能性があります 大きいです。

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

    実行計画だけでなく、コールスタックのさまざまなアプローチを確認することができます。

    直接ストリーミング

    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    
    

    サブクエリあり

    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
    

    どちらも同じ基になるXMLコードを呼び出すことになりますが、「ラップされていない」バージョンにはプラン自体にXMLイテレーターが含まれていません。結果は、CXStmtSelectからのメソッド呼び出しを置き換えることで実現されます。 CXStmtXMLSelectを使用 代わりに(プランでは、単純な古いSelectではなくXML Selectルートノードとして表されます)。

    SQL Server 2016 CTP3でも、ntextが表示されます トップレベルのFOR XML 。ただし、トップレベルのFOR JSON nvarchar(max)として表示されます

    少なくともCTPでは、JSON特殊列名にGUID F52E2B61-18A1-11d1-B105-00805F49916Bが含まれています。 これの起源はIXMLDocumentインターフェイスであるという事実にもかかわらず。

    XMLSelectがJSONSelectに置き換えられていますが、計画はほとんど同じように見えます

    ところで:ビルド時Microsoft SQL Server 2014 - 12.0.4213.0 (X64) 一時テーブルと永続テーブルの動作に違いは見られません。これはおそらく別の@@Versionによるものです 質問が使用する環境間では、http://sqlfiddle.com/(12.0.2000.8)とhttps://data.stackexchange.com/(12.0.4213.0)が使用されます。

    sys.dm_exec_describe_first_result_setでバグが修正された可能性があります 2つの2014ビルドの間。

    2012年には、11.0.5343.0のShnugoと同じ結果が得られます(NULL 最初の3行)ですが、SP3 11.0.6020.0をインストールした後、質問に示されている最初の結果と同じ結果が得られます。



    1. 作成済みのデータベースをアセットからコピーできません

    2. ContentDocumentをSalesforceカスタムオブジェクトに添付する

    3. OracleのJoinクエリで更新

    4. Oracleのピボットテーブルを使用したアドバイス