今から実行するクエリの実行プランが欲しい

SSMS(SQL Server Management Studio) や SQL Database の管理ポータルなんかでは、 クエリを実行する時に一緒に実行プランも取得出来ます。
これを自前でやりたい場合は、SET SHOWPLAN_XML (Transact-SQL) を使います。

サンプルをもとに早速 SSMS から試してみましょう。

SET SHOWPLAN_XML ON
go
select * from 社員 where Id <= 100
go
SET SHOWPLAN_XML OFF

実行結果はこちら

XML をクリックすると、SSMS で見るいつもの感じで見れます。

今回は SSMS からの実行は別にどうでも良いので C# から試してみます。

using System;
using System.Data.SqlClient;

class Program {
  static void Main(string[] args) {
    var connStr = @"Data Source=localhost\MSSQL2014;
Initial Catalog=database1;
Integrated Security=True";
    using (var conn = new SqlConnection(connStr))
    using (var cmd = new SqlCommand(@"SET SHOWPLAN_XML ON
go
select * from 社員 where Id <= 100
go
SET SHOWPLAN_XML OFF
", conn)) {
      conn.Open();
      Console.WriteLine(cmd.ExecuteScalar());        
    }
    Console.ReadKey();
  }
}

これを動かすと「'go' 付近に不適切な構文があります。」と SQLException が吐かれます。
GO - お だ のスペース で書きましたが、GO は T-SQL ではなく SSMS 等からクエリを投げる際に使われるものです。
かといって go を省いたクエリにすると、
「SET SHOWPLAN ステートメントはバッチ内のステートメントとしてだけ使用できます。」とエラーが出ます。
どうすればよいのかというと、go の区切り毎に SqlCommand で Execute してあげるのが正解です。

using (var conn = new SqlConnection(connStr))
using (var cmd = new SqlCommand(@"SET SHOWPLAN_XML ON", conn)) {
  conn.Open();
  cmd.ExecuteNonQuery();
  cmd.CommandText = "select * from 社員 where Id <= 100";
  Console.WriteLine(cmd.ExecuteScalar());
}


とれてますね。SET SHOWPLAN_XML OFF はどうせこれで接続切るし…ということで投げてません。
この後も同じコネクションを使ってクエリを投げたい場合は、SET SHOWPLAN_XML OFF も投げときましょう。