我可以很容易地将数据转储到文本文件中,例如:
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个字符(这需要与最长的行一样宽,否则它将换行到下一行)
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参考.它使/?
选项的输出变得羞耻.
使用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模块,其中包含Invoke-Sqlcmd
cmdlet,即使您刚刚安装SSMS 2016,它也将拥有该模块.在此之前,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
完全删除该行,并使用sqlps.exe实用程序而不是标准PowerShell主机.
Invoke-Sqlcmd是与sqlcmd.exe等效的PowerShell.而不是文本它输出System.Data.DataRow对象.
该-Query
参数的作用类似于-Q
sqlcmd.exe 的参数.传递一个描述要导出的数据的SQL查询.
该-Database
参数的作用类似于-d
sqlcmd.exe 的参数.传递包含要导出的数据的数据库的名称.
该-Server
参数的作用类似于-S
sqlcmd.exe 的参数.将它传递给包含要导出的数据的服务器的名称.
Export-CSV是一个PowerShell cmdlet,它将通用对象序列化为CSV.它附带PowerShell.
该-NoTypeInformation
参数抑制了不属于CSV格式的额外输出.默认情况下,cmdlet会写入包含类型信息的标头.它可以让您在以后反序列化时知道对象的类型Import-Csv
,但它会混淆期望标准CSV的工具.
该-Path
参数的作用类似于-o
sqlcmd.exe 的参数.如果您使用旧的SQLPS模块,则此值的完整路径是最安全的.
该-Encoding
参数的工作方式类似于-f
或-u
sqlcmd.exe的参数.默认情况下,Export-Csv仅输出ASCII字符,并用问号替换所有其他字符.使用UTF8代替保留所有字符并与大多数其他工具保持兼容.
此解决方案优于sqlcmd.exe或bcp.exe的主要优点是您不必破解命令输出有效的CSV.Export-Csv cmdlet可以为您处理所有内容.
主要缺点是Invoke-Sqlcmd
在沿管道传递之前读取整个结果集.确保您有足够的内存用于要导出的整个结果集.
数十亿行可能无法顺利运行.如果这是一个问题,您可以尝试其他工具,或Invoke-Sqlcmd
使用 System.Data.SqlClient.SqlDataReader类滚动自己的高效版本.
这不是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文档页面.
上面的例子:
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过滤掉该行.请注意,它不是完美的,因为它过滤掉-,-
- 如果输出中只有一列,它将无效,并且它还会过滤掉包含该字符串的合法行.