With PowerShell you can solve the problem neatly by piping Invoke-Sqlcmd into 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 includes the SqlServer module, which contains the Invoke-Sqlcmd
cmdlet, which you'll have even if you just install SSMS 2016. Prior to that, SQL Server 2012 included the old SQLPS module, which would change the current directory to SQLSERVER:\
when the module was first used (among other bugs) so for it, you'll need to change the #Requires
line above to:
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
To adapt the example for SQL Server 2008 and 2008 R2, remove the #Requires
line entirely and use the sqlps.exe utility instead of the standard PowerShell host.
Invoke-Sqlcmd is the PowerShell equivalent of sqlcmd.exe. Instead of text it outputs System.Data.DataRow objects.
The -Query
parameter works like the -Q
parameter of sqlcmd.exe. Pass it a SQL query that describes the data you want to export.
The -Database
parameter works like the -d
parameter of sqlcmd.exe. Pass it the name of the database that contains the data to be exported.
The -Server
parameter works like the -S
parameter of sqlcmd.exe. Pass it the name of the server that contains the data to be exported.
Export-CSV is a PowerShell cmdlet that serializes generic objects to CSV. It ships with PowerShell.
The -NoTypeInformation
parameter suppresses extra output that is not part of the CSV format. By default the cmdlet writes a header with type information. It lets you know the type of the object when you deserialize it later with Import-Csv
, but it confuses tools that expect standard CSV.
The -Path
parameter works like the -o
parameter of sqlcmd.exe. A full path for this value is safest if you are stuck using the old SQLPS module.
The -Encoding
parameter works like the -f
or -u
parameters of sqlcmd.exe. By default Export-Csv outputs only ASCII characters and replaces all others with question marks. Use UTF8 instead to preserve all characters and stay compatible with most other tools.
The main advantage of this solution over sqlcmd.exe or bcp.exe is that you don't have to hack the command to output valid CSV. The Export-Csv cmdlet handles it all for you.
The main disadvantage is that Invoke-Sqlcmd
reads the whole result set before passing it along the pipeline. Make sure you have enough memory for the whole result set you want to export.
It may not work smoothly for billions of rows. If that's a problem, you could try the other tools, or roll your own efficient version of Invoke-Sqlcmd
using System.Data.SqlClient.SqlDataReader class.