C#でのGOコマンドを含む大きなSQLスクリプトの実行

SQL Serverを扱う際、テーブル、ビュー、ストアドプロシージャなどの複数のオブジェクトを作成する大きなSQLスクリプトに直面することが一般的です。これらのスクリプトは、多くの場合、GOコマンドで区切られています。C#プログラムからこのようなスクリプトを実行しようとすると、問題が発生するかもしれません。SqlCommand.ExecuteNonQuery()メソッドはGOコマンドを認識しないため、エラーやSQLステートメントの不完全な実行につながる可能性があります。

では、この状況を効果的に処理するにはどうすれば良いのでしょうか?プロセスを簡素化するソリューションを探ってみましょう。

問題の理解

主な課題は、C#のSqlCommandクラスがGOをバッチセパレーターとしてサポートしていないことです。各バッチは別々にサーバーに送信する必要があります。以下は、GOコマンドを含むスクリプトを実行する際の手順の概要です:

  1. スクリプト準備:SQLスクリプトが作成され、GOで区切られた複数のステートメントを含む必要があります。
  2. SQLコマンド実行:スクリプトを実行するためのコマンドを使用します。しかし、スクリプト全体を直接実行すると、GOの含有によりエラーが発生します。
  3. バッチ実行:スクリプトをGOコマンドなしにそれぞれ別のバッチに分割し、1つずつ実行します。

しかし、スクリプトを手動で分割することは煩雑でエラーを引き起こしやすいです。幸いにも、より良い方法があります。

より良いソリューション:SQL Server Management Objects (SMO) の使用

GOステートメントを含む大きなSQLスクリプトを実行する最も効果的な方法の1つは、SQL Server Management Objects (SMO)を使用することです。SMOはGOセパレーターを理解し、スクリプトを意図した通りに実行できます。

実装手順

このソリューションをC#プログラムに実装する方法は以下の通りです:

  1. 環境の設定:プロジェクトに必要なSMOライブラリへの参照を追加します。まだ行っていない場合は、NuGetを通じてMicrosoft.SqlServer.SqlManagementObjectsパッケージをインストールする必要があります。

  2. サンプルコード:以下は、SMOを使用してSQLスクリプトを実行するためのサンプル実装です:

public static void Main()    
{        
    // SQLスクリプトが含まれるディレクトリを定義
    string scriptDirectory = "c:\\temp\\sqltest\\";
    
    // SQL Serverデータベースの接続文字列を定義
    string sqlConnectionString = "Integrated Security=SSPI;" +
                                 "Persist Security Info=True;Initial Catalog=Northwind;Data Source=(local)";
    
    // 指定したディレクトリから全てのSQLファイルを取得
    DirectoryInfo di = new DirectoryInfo(scriptDirectory);
    FileInfo[] rgFiles = di.GetFiles("*.sql");
    
    // 各SQLファイルをループ処理
    foreach (FileInfo fi in rgFiles)
    {
        // SQLファイルの内容を読み取る
        string script = File.ReadAllText(fi.FullName);
        
        // 新しいSQL接続を作成
        using (SqlConnection connection = new SqlConnection(sqlConnectionString))
        {
            // SMOサーバーオブジェクトを初期化
            Server server = new Server(new ServerConnection(connection));
            server.ConnectionContext.ExecuteNonQuery(script); // スクリプトを実行
        }
    }
}

コードの説明

  • スクリプトディレクトリscriptDirectory変数を、SQLファイルが保存されているフォルダーに変更します。
  • SQL接続文字列:接続文字列をデータベースサーバーの設定に合わせて修正します。
  • ファイル操作:コードはFile.ReadAllTextを使って、それぞれのSQLファイルの内容を読み取ります。
  • SMO実行server.ConnectionContext.ExecuteNonQuery(script)コマンドがGOコマンドを適切に処理しながらスクリプトを実行します。

代替ソリューション

もしSMOがプロジェクトに適さない場合は、次のことを考慮できます:

  • Phil HaackのライブラリGOセパレーターを扱うアシストライブラリ。実装の詳細は彼のブログ投稿で確認できます こちら

結論

GOコマンドを含む大きなSQLスクリプトを実行することは、頭痛の種である必要はありません。SQL Server Management Objects (SMO)を利用することで、コマンドを手動で分割する手間なく、スムーズに構造化された方法でスクリプトを実行できます。このアプローチは、時間を節約するだけでなく、実行中のエラーの可能性を減少させます。

最良の結果を得るためには、環境を正しく設定し、C#アプリケーションでのSQL実行体験を快適にEnjoyしましょう。