使用 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 包含旧的 @ 987654321@,当第一次使用模块时(以及其他错误)会将当前目录更改为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 utility 而不是标准 PowerShell 主机。
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 cmdlet。它随 PowerShell 一起提供。
-NoTypeInformation 参数抑制不属于 CSV 格式的额外输出。默认情况下,cmdlet 会写入带有类型信息的标头。当您稍后使用 Import-Csv 反序列化对象时,它可以让您知道对象的类型,但它会混淆需要标准 CSV 的工具。
-Path 参数的作用类似于 sqlcmd.exe 的 -o 参数。如果您在使用旧的 SQLPS 模块时遇到问题,则此值的完整路径是最安全的。
-Encoding 参数的作用类似于 sqlcmd.exe 的 -f 或 -u 参数。默认情况下,Export-Csv 仅输出 ASCII 字符并用问号替换所有其他字符。改用 UTF8 来保留所有字符并与大多数其他工具保持兼容。
与 sqlcmd.exe 或 bcp.exe 相比,此解决方案的主要优点是您无需破解命令即可输出有效的 CSV。 Export-Csv cmdlet 会为您处理这一切。
主要缺点是Invoke-Sqlcmd 在通过管道传递之前读取整个结果集。确保您有足够的内存用于要导出的整个结果集。
对于数十亿行,它可能无法顺利运行。如果这是一个问题,您可以尝试其他工具,或者使用 System.Data.SqlClient.SqlDataReader 类推出您自己的高效版本的Invoke-Sqlcmd。