none
バッチ処理で実行したSQLCMDからのリダイレクトを補足できない RRS feed

  • 質問


  • SQL Server 2014 Expressからのクエリー結果を処理するプログラムを作成しています。
    (1)のBATファイルでSQLCMDから単純な文字列の出力を受信して、C:\014.txtに書き込みます。

    (2)は、(1)から呼び出されるバッチファイルです。

    (1)をコマンドプロンプトで実行すると、常に正常に処理されますが、(3)で示したコードのプログラムから実行すると、ファイル容量0バイトのC:\014.txtが作成されるだけです。

    DIR C:\ > C:\014.txt という内容のBATファイルについては、正常にC:\014.txtが出力されます。

    なぜ、SQLCMDをバッチファイルで実行した時は結果が返されないのでしょうか。
    御教授をよろしくお願い致します。


    環境:
    SQL Server 2014 Expressを入れたサーバーは、SQLCMDを実行するクライアントとはTCPで接続が確認されています。
    プログラムを作成中のクライアント Windows 7 + VS 2010,SQLCMD.exeのバージョンは13の最新版です。

    ---------


    (1) C:\001.batの内容(XXXXX-PCのサーバーにsaというユーザー名、Passwordというパスワードで接続し、"C:\011a.bat"に書かれたバッチを実行する)

    SQLCMD -S XXXXX-PC -U sa -P Password -i "C:\011a.bat"  >  "C:\014.txt"

    (2) C:\011a.batの内容(リモート接続されたSQLサーバーが返したバージョン情報を得る)

    print @@version

    (3) ソースコード

        Private Sub MainWindow_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded

            Dim p As New System.Diagnostics.Process()

            p.StartInfo.FileName = System.Environment.GetEnvironmentVariable("ComSpec")
            p.StartInfo.UseShellExecute = False
            p.StartInfo.RedirectStandardOutput = True
            p.StartInfo.RedirectStandardInput = False
            p.StartInfo.CreateNoWindow = True
            p.StartInfo.Arguments = "/c c:\001.bat"
            p.Start()

            p.WaitForExit()
            p.Close()

            Me.Close()

        End Sub
    2017年4月26日 23:55

回答

  • (2) C:\011a.batの内容(リモート接続されたSQLサーバーが返したバージョン情報を得る)

    print @@version

    ここに勘違いがあります。
    これだと、T-SQLのprintではなく、MS-DOSのprintが実行されてしまいます。
    (1)の -i ではSQLが書かれているファイルを単に指定するだけですので、T-SQLのprintと解釈され、正しく実行されます。しかし、(3)ではMS-DOSのprintとして実行されてしまうため、うまく行きません。
    訂正するのであれば、例えば以下のようになります。

    011a.sqlというファイルを新たに作成する。その中身は、
    print @@version

    011a.batの中身を次のように修正する。

    SQLCMD -S XXXXX-PC -U sa -P Password -i "C:\011a.sql"  >  "C:\014.txt"

    以上で、うまく行くはずです。

    (追記)
    #  p.StartInfo.Arguments = "/c c:\001.bat" となっていますが、ここは011a.batですよね?


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/



    2017年4月28日 1:18
    モデレータ

すべての返信

  • タイトルが間違っていました。

    ×「補足」

    ○「捕捉」

    訂正します。

    2017年4月27日 0:00
  • (2) C:\011a.batの内容(リモート接続されたSQLサーバーが返したバージョン情報を得る)

    print @@version

    ここに勘違いがあります。
    これだと、T-SQLのprintではなく、MS-DOSのprintが実行されてしまいます。
    (1)の -i ではSQLが書かれているファイルを単に指定するだけですので、T-SQLのprintと解釈され、正しく実行されます。しかし、(3)ではMS-DOSのprintとして実行されてしまうため、うまく行きません。
    訂正するのであれば、例えば以下のようになります。

    011a.sqlというファイルを新たに作成する。その中身は、
    print @@version

    011a.batの中身を次のように修正する。

    SQLCMD -S XXXXX-PC -U sa -P Password -i "C:\011a.sql"  >  "C:\014.txt"

    以上で、うまく行くはずです。

    (追記)
    #  p.StartInfo.Arguments = "/c c:\001.bat" となっていますが、ここは011a.batですよね?


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/



    2017年4月28日 1:18
    モデレータ
  • trepemiyaさん
    御回答ありがとうございます。

    御指示の通りにしたら動作しました。
    SQLCMD の -iオプションで指定するファイル名を "***.bat" から"***.sql"にすると、動作することがわかりました。

    なぜコマンドプロンプトと.Netアプリケーション実行時でSQLCMDの挙動が違うのか、私にはわかりませんが、今後SQLCMDを使う時は注意したいと思います。

    今回開発するプログラムの仕様は、SQLCMDでデータベースのクエリーと、バックアップ・復元の終了メッセージをクリップボードにコピーして収集するというものです。
    以上のことは、先程プログラムを完成させることができました。

    的確な御回答、誠にありがとうございました。
    2017年4月28日 2:18