トップ回答者
バッチ処理で実行したSQLCMDからのリダイレクトを補足できない

質問
-
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
回答
-
(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 @@version011a.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/
- 編集済み trapemiyaModerator 2017年4月28日 1:21 追記
- 回答としてマーク huahi11112 2017年4月28日 2:17
すべての返信
-
(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 @@version011a.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/
- 編集済み trapemiyaModerator 2017年4月28日 1:21 追記
- 回答としてマーク huahi11112 2017年4月28日 2:17
-
trepemiyaさん
御回答ありがとうございます。
御指示の通りにしたら動作しました。
SQLCMD の -iオプションで指定するファイル名を "***.bat" から"***.sql"にすると、動作することがわかりました。
なぜコマンドプロンプトと.Netアプリケーション実行時でSQLCMDの挙動が違うのか、私にはわかりませんが、今後SQLCMDを使う時は注意したいと思います。
今回開発するプログラムの仕様は、SQLCMDでデータベースのクエリーと、バックアップ・復元の終了メッセージをクリップボードにコピーして収集するというものです。
以上のことは、先程プログラムを完成させることができました。
的確な御回答、誠にありがとうございました。