次のようなテキスト ファイルにデータを簡単にダンプできます。
sqlcmd -S myServer -d myDB -E -Q "select col1, col2, col3 from SomeTable"
-o "MyData.txt"
ただし、ヘルプ ファイルをSQLCMD
見ましたが、CSV 専用のオプションは見当たりませんでした。
を使用してテーブルから CSV テキスト ファイルにデータをダンプする方法はありますSQLCMD
か?
次のようなテキスト ファイルにデータを簡単にダンプできます。
sqlcmd -S myServer -d myDB -E -Q "select col1, col2, col3 from SomeTable"
-o "MyData.txt"
ただし、ヘルプ ファイルをSQLCMD
見ましたが、CSV 専用のオプションは見当たりませんでした。
を使用してテーブルから CSV テキスト ファイルにデータをダンプする方法はありますSQLCMD
か?
次のようなものを実行できます。
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 文字に設定します (これは、最も長い行と同じ幅にする必要があります。そうしないと、次の行に折り返されます)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 には、SSMS 2016 をインストールしただけでも使用できるコマンドレットを含むSqlServerモジュールが含まれています。それ以前は、SQL Server 2012 には古いSQLPSモジュールが含まれていました。これにより、現在のディレクトリがモジュールがインストールされた時点に変更されます。 (他のバグの中でも)最初に使用されたため、上記の行を次のように変更する必要があります。Invoke-Sqlcmd
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オブジェクトを出力します。
このパラメーターは、sqlcmd.exe-Query
のパラメーターと同様に機能します。-Q
エクスポートするデータを記述する SQL クエリを渡します。
このパラメーターは、sqlcmd.exe-Database
のパラメーターと同様に機能します。-d
エクスポートするデータを含むデータベースの名前を渡します。
このパラメーターは、sqlcmd.exe-Server
のパラメーターと同様に機能します。-S
エクスポートするデータを含むサーバーの名前を渡します。
Export-CSVは、汎用オブジェクトを CSV にシリアル化する PowerShell コマンドレットです。PowerShell に同梱されています。
この-NoTypeInformation
パラメーターは、CSV 形式の一部ではない余分な出力を抑制します。既定では、コマンドレットは型情報を含むヘッダーを書き込みます。後で で逆シリアル化するときにオブジェクトのタイプを知ることができますが、Import-Csv
標準の CSV を期待するツールを混乱させます。
このパラメーターは、sqlcmd.exe-Path
のパラメーターと同様に機能します。古いSQLPSモジュール-o
を使用している場合は、この値のフル パスが最も安全です。
パラメータは、sqlcmd.exeのまたはパラメータの-Encoding
ように機能します。デフォルトでは、Export-Csv は ASCII 文字のみを出力し、その他すべてを疑問符に置き換えます。代わりに UTF8 を使用して、すべての文字を保持し、他のほとんどのツールとの互換性を維持してください。-f
-u
sqlcmd.exe または bcp.exe に対するこのソリューションの主な利点は、有効な CSV を出力するためにコマンドをハックする必要がないことです。Export-Csv コマンドレットがすべてを処理します。
主な欠点はInvoke-Sqlcmd
、パイプラインに沿って渡す前に結果セット全体を読み取ることです。エクスポートする結果セット全体に十分なメモリがあることを確認してください。
数十億行の場合、スムーズに機能しない場合があります。それが問題である場合は、他のツールを試すか、System.Data.SqlClient.SqlDataReaderクラスをInvoke-Sqlcmd
使用し て独自の効率的なバージョンを作成することができます。
sqlcmd -S myServer -d myDB -E -o "MyData.txt" ^
-Q "select bar from foo" ^
-W -w 999 -s","
最後の行には、CSV 固有のオプションが含まれています。
-W
個々のフィールドから末尾のスペースを削除する-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 ユーティリティドキュメント ページ。
上記のページの例:
bcp.exe MyTable out "D:\data.csv" -T -c -C 65001 -t , ...
これを行おうとしているが、列ヘッダーも持っている人へのメモ。これは、バッチファイルを使用した解決策です。
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 '
ハックな方法でそれを行うことができます。sqlcmd
ハックの使用には注意してください。データに二重引用符またはコンマが含まれていると、問題が発生します。
簡単なスクリプトを使用して、適切に実行できます。
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Data Exporter '
' '
' Description: Allows the output of data to CSV file from a SQL '
' statement to either Oracle, SQL Server, or MySQL '
' Author: C. Peter Chen, http://dev-notes.com '
' Version Tracker: '
' 1.0 20080414 Original version '
' 1.1 20080807 Added email functionality '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
option explicit
dim dbType, dbHost, dbName, dbUser, dbPass, outputFile, email, subj, body, smtp, smtpPort, sqlstr
'''''''''''''''''
' Configuration '
'''''''''''''''''
dbType = "oracle" ' Valid values: "oracle", "sqlserver", "mysql"
dbHost = "dbhost" ' Hostname of the database server
dbName = "dbname" ' Name of the database/SID
dbUser = "username" ' Name of the user
dbPass = "password" ' Password of the above-named user
outputFile = "c:\output.csv" ' Path and file name of the output CSV file
email = "email@me.here" ' Enter email here should you wish to email the CSV file (as attachment); if no email, leave it as empty string ""
subj = "Email Subject" ' The subject of your email; required only if you send the CSV over email
body = "Put a message here!" ' The body of your email; required only if you send the CSV over email
smtp = "mail.server.com" ' Name of your SMTP server; required only if you send the CSV over email
smtpPort = 25 ' SMTP port used by your server, usually 25; required only if you send the CSV over email
sqlStr = "select user from dual" ' SQL statement you wish to execute
'''''''''''''''''''''
' End Configuration '
'''''''''''''''''''''
dim fso, conn
'Create filesystem object
set fso = CreateObject("Scripting.FileSystemObject")
'Database connection info
set Conn = CreateObject("ADODB.connection")
Conn.ConnectionTimeout = 30
Conn.CommandTimeout = 30
if dbType = "oracle" then
conn.open("Provider=MSDAORA.1;User ID=" & dbUser & ";Password=" & dbPass & ";Data Source=" & dbName & ";Persist Security Info=False")
elseif dbType = "sqlserver" then
conn.open("Driver={SQL Server};Server=" & dbHost & ";Database=" & dbName & ";Uid=" & dbUser & ";Pwd=" & dbPass & ";")
elseif dbType = "mysql" then
conn.open("DRIVER={MySQL ODBC 3.51 Driver}; SERVER=" & dbHost & ";PORT=3306;DATABASE=" & dbName & "; UID=" & dbUser & "; PASSWORD=" & dbPass & "; OPTION=3")
end if
' Subprocedure to generate data. Two parameters:
' 1. fPath=where to create the file
' 2. sqlstr=the database query
sub MakeDataFile(fPath, sqlstr)
dim a, showList, intcount
set a = fso.createtextfile(fPath)
set showList = conn.execute(sqlstr)
for intcount = 0 to showList.fields.count -1
if intcount <> showList.fields.count-1 then
a.write """" & showList.fields(intcount).name & ""","
else
a.write """" & showList.fields(intcount).name & """"
end if
next
a.writeline ""
do while not showList.eof
for intcount = 0 to showList.fields.count - 1
if intcount <> showList.fields.count - 1 then
a.write """" & showList.fields(intcount).value & ""","
else
a.write """" & showList.fields(intcount).value & """"
end if
next
a.writeline ""
showList.movenext
loop
showList.close
set showList = nothing
set a = nothing
end sub
' Call the subprocedure
call MakeDataFile(outputFile,sqlstr)
' Close
set fso = nothing
conn.close
set conn = nothing
if email <> "" then
dim objMessage
Set objMessage = CreateObject("CDO.Message")
objMessage.Subject = "Test Email from vbs"
objMessage.From = email
objMessage.To = email
objMessage.TextBody = "Please see attached file."
objMessage.AddAttachment outputFile
objMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
objMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = smtp
objMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = smtpPort
objMessage.Configuration.Fields.Update
objMessage.Send
end if
'You're all done!! Enjoy the file created.
msgbox("Data Writer Done!")