次のようなテキストファイルにデータを簡単にダンプできます。
sqlcmd -S myServer -d myDB -E -Q "select col1, col2, col3 from SomeTable"
-o "MyData.txt"
ただし、SQLCMD
のヘルプファイルを見ましたが、CSV専用のオプションは見ていません。
SQLCMD
を使用して、テーブルのデータをCSVテキストファイルにダンプする方法はありますか?
次のようなものを実行できます。
sqlcmd -S MyServer -d myDB -E -Q "select col1, col2, col3 from SomeTable"
-o "MyData.csv" -h-1 -s"," -w 700
-h-1
は結果から列名ヘッダーを削除します-s","
は列セパレーターをに設定します-w 700
は行の幅を700文字に設定します(これは最も長い行と同じ幅にする必要があります。そうしないと、次の行に折り返されます)sqlcmd -S myServer -d myDB -E -o "MyData.txt" ^
-Q "select bar from foo" ^
-W -w 999 -s","
最後の行には、CSV固有のオプションが含まれています。
-W
individual各フィールドから末尾のスペースを削除します-s","
は、列セパレーターをコンマ(、)に設定します-w 999
は行幅を999文字に設定しますscottmの答え は私が使用しているものに非常に近いですが、私は-W
が本当に素晴らしい追加であることがわかりました:CSVを他の場所で消費するときに空白をトリミングする必要はありません。
MSDN sqlcmdリファレンス も参照してください。 /?
オプションの出力を恥じます。
これはbcp
が意図したものではありませんか?
bcp "select col1, col2, col3 from database.schema.SomeTable" queryout "c:\MyData.txt" -c -t"," -r"\n" -S ServerName -T
コマンドラインからこれを実行して、構文を確認してください。
bcp /?
例えば:
usage: bcp {dbtable | query} {in | out | queryout | format} datafile
[-m maxerrors] [-f formatfile] [-e errfile]
[-F firstrow] [-L lastrow] [-b batchsize]
[-n native type] [-c character type] [-w wide character type]
[-N keep non-text native] [-V file format version] [-q quoted identifier]
[-C code page specifier] [-t field terminator] [-r row terminator]
[-i inputfile] [-o outfile] [-a packetsize]
[-S server name] [-U username] [-P password]
[-T trusted connection] [-v version] [-R regional enable]
[-k keep null values] [-E keep identity values]
[-h "load hints"] [-x generate xml format file]
[-d database name]
bcp
は列ヘッダーを出力できないことに注意してください。
参照: bcp Utility docs page。
上記ページの例:
bcp.exe MyTable out "D:\data.csv" -T -c -C 65001 -t , ...
PowerShellを使用すると、Invoke-SqlcmdをExport-Csvにパイプすることで問題をきれいに解決できます。
#Requires -Module SqlServer
Invoke-Sqlcmd -Query "SELECT * FROM DimDate;" `
-Database AdventureWorksDW2012 `
-Server localhost |
Export-Csv -NoTypeInformation `
-Path "DimDate.csv" `
-Encoding UTF8
SQL Server 2016には、SqlServerモジュールが含まれています。このモジュールには、SSMS 2016をインストールしただけでも使用できるInvoke-Sqlcmd
コマンドレットが含まれています。それ以前は、SQL Server 2012には古い SQLPSモジュール が含まれていました。これにより、モジュールが最初に使用されたときに現在のディレクトリがSQLSERVER:\
に変更されます(その他のバグの中で)そのため、上記の#Requires
行を次のように変更する必要があります:
Push-Location $PWD
Import-Module -Name SQLPS
# dummy query to catch initial surprise directory change
Invoke-Sqlcmd -Query "SELECT 1" `
-Database AdventureWorksDW2012 `
-Server localhost |Out-Null
Pop-Location
# actual Invoke-Sqlcmd |Export-Csv pipeline
サンプルをSQL Server 2008および2008 R2に適合させるには、#Requires
行を完全に削除し、標準のPowerShellホストの代わりに sqlps.exeユーティリティ を使用します。
Invoke-Sqlcmd は、sqlcmd.exeと同等のPowerShellです。テキストの代わりに System.Data.DataRow オブジェクトを出力します。
-Query
パラメーターは、sqlcmd.exeの-Q
パラメーターと同様に機能します。エクスポートするデータを記述するSQLクエリを渡します。
-Database
パラメーターは、sqlcmd.exeの-d
パラメーターと同様に機能します。エクスポートするデータを含むデータベースの名前を渡します。
-Server
パラメーターは、sqlcmd.exeの-S
パラメーターと同様に機能します。エクスポートするデータを含むサーバーの名前を渡します。
Export-CSV は、汎用オブジェクトをCSVにシリアル化するPowerShellコマンドレットです。 PowerShellが付属しています。
-NoTypeInformation
パラメーターは、CSV形式の一部ではない余分な出力を抑制します。既定では、コマンドレットは型情報を含むヘッダーを書き込みます。後でImport-Csv
を使用してオブジェクトをデシリアライズするときにオブジェクトのタイプを知ることができますが、標準のCSVを期待するツールを混乱させます。
-Path
パラメーターは、sqlcmd.exeの-o
パラメーターと同様に機能します。古いSQLPSモジュールを使用してスタックしている場合、この値の絶対パスが最も安全です。
-Encoding
パラメーターは、sqlcmd.exeの-f
または-u
パラメーターと同様に機能します。デフォルトでは、Export-CsvはASCII文字のみを出力し、他のすべてを疑問符に置き換えます。代わりにUTF8を使用して、すべての文字を保持し、他のほとんどのツールとの互換性を維持します。
Sqlcmd.exeまたはbcp.exeに対するこのソリューションの主な利点は、有効なCSVを出力するためにコマンドをハッキングする必要がないことです。 Export-Csvコマンドレットがすべてを処理します。
主な欠点は、Invoke-Sqlcmd
が結果セット全体を読み取ってからパイプラインに渡すことです。エクスポートする結果セット全体に十分なメモリがあることを確認してください。
何十億行もスムーズに動作しない場合があります。それが問題になる場合は、他のツールを試すか、 System.Data.SqlClient.SqlDataReader クラスを使用して、独自のInvoke-Sqlcmd
の効率的なバージョンを実行できます。
これを実行したいが、列ヘッダーも持っている人のためのメモは、これが私がバッチファイルを使用した解決策です:
sqlcmd -S servername -U username -P password -d database -Q "set nocount on; set ansi_warnings off; sql query here;" -o output.tmp -s "," -W
type output.tmp | findstr /V \-\,\- > output.csv
del output.tmp
これにより、最初の結果(ヘッダーとデータ間の----、----セパレーターを含む)が一時ファイルに出力され、findstrでフィルター処理してその行が削除されます。 -,-
を除外するため完全ではないことに注意してください。出力に列が1つしかない場合は機能せず、その文字列を含む正当な行も除外します。
BCPの代替オプション:
exec master..xp_cmdshell 'BCP "sp_who" QUERYOUT C:\av\sp_who.txt -S MC0XENTC -T -c '
この答えは、@ iain-elderのソリューションに基づいています。これは、大規模なデータベースの場合を除いてうまく機能します(彼のソリューションで指摘されています)。テーブル全体がシステムのメモリに収まる必要がありますが、私にとってこれは選択肢ではありませんでした。 System.Data.SqlClient.SqlDataReader とカスタムCSVシリアライザー( 例についてはこちらを参照 )またはMS SQLドライバーを使用する別の言語を使用するのが最善のソリューションだと思いますCSVシリアル化。おそらく依存関係のないソリューションを探していた元の質問の精神で、以下のPowerShellコードがうまくいきました。特に、$ data配列をインスタンス化し、$ chunk_size行ごとに追加モードでExport-Csvを呼び出す場合、非常に遅く、非効率的です。
$chunk_size = 10000
$command = New-Object System.Data.SqlClient.SqlCommand
$command.CommandText = "SELECT * FROM <TABLENAME>"
$command.Connection = $connection
$connection.open()
$reader = $command.ExecuteReader()
$read = $TRUE
while($read){
$counter=0
$DataTable = New-Object System.Data.DataTable
$first=$TRUE;
try {
while($read = $reader.Read()){
$count = $reader.FieldCount
if ($first){
for($i=0; $i -lt $count; $i++){
$col = New-Object System.Data.DataColumn $reader.GetName($i)
$DataTable.Columns.Add($col)
}
$first=$FALSE;
}
# Better way to do this?
$data=@()
$emptyObj = New-Object System.Object
for($i=1; $i -le $count; $i++){
$data += $emptyObj
}
$reader.GetValues($data) | out-null
$DataRow = $DataTable.NewRow()
$DataRow.ItemArray = $data
$DataTable.Rows.Add($DataRow)
$counter += 1
if ($counter -eq $chunk_size){
break
}
}
$DataTable | Export-Csv "output.csv" -NoTypeInformation -Append
}catch{
$ErrorMessage = $_.Exception.Message
Write-Output $ErrorMessage
$read=$FALSE
$connection.Close()
exit
}
}
$connection.close()
次の2つの理由から、CMDで私のソリューションを実行する必要があります。
リモートのSQL Serverインスタンスを照会するには、ログインユーザー名とパスワードが必要な場合があります
sqlcmd -U [your_User] -P[your_password] -S [your_remote_Server] -d [your_databasename] -i "query.txt" -o "output.csv" -s"," -w 700
通常、sqlcmd
には bcp
ユーティリティ (mssql-tools
の一部として)が付属しており、デフォルトでCSVにエクスポートされます。
使用法:
bcp {dbtable | query} {in | out | queryout | format} datafile
例えば:
bcp.exe MyTable out data.csv
すべてのテーブルを対応するCSVファイルにダンプするためのBashスクリプトを次に示します。
#!/usr/bin/env bash
# Script to dump all tables from SQL Server into CSV files via bcp.
# @file: bcp-dump.sh
server="sql.example.com" # Change this.
user="USER" # Change this.
pass="PASS" # Change this.
dbname="DBNAME" # Change this.
creds="-S '$server' -U '$user' -P '$pass' -d '$dbname'"
sqlcmd $creds -Q 'SELECT * FROM sysobjects sobjects' > objects.lst
sqlcmd $creds -Q 'SELECT * FROM information_schema.routines' > routines.lst
sqlcmd $creds -Q 'sp_tables' | tail -n +3 | head -n -2 > sp_tables.lst
sqlcmd $creds -Q 'SELECT name FROM sysobjects sobjects WHERE xtype = "U"' | tail -n +3 | head -n -2 > tables.lst
for table in $(<tables.lst); do
sqlcmd $creds -Q "exec sp_columns $table" > $table.desc && \
bcp $table out $table.csv -S $server -U $user -P $pass -d $dbname -c
done
上記の答えは私にとってほとんど解決しましたが、解析されたCSVを正しく作成しません。
これが私のバージョンです。
sqlcmd -S myurl.com -d MyAzureDB -E -s, -W -i mytsql.sql | findstr /V /C:"-" /B > parsed_correctly.csv
sqlcmd
は時代遅れだと言って、PowerShellの代替を支持する人は、sqlcmd
がWindowsだけのものではないことを忘れています。私はLinuxを使用しています(Windowsの場合はPSを避けます)。
そうは言っても、bcp
の方が簡単です。