How to Export Data From SQL Server to Excel (6 Tested Methods)

Say your finance lead in Boston wants this month’s customer balances in a spreadsheet, ZIP codes and all.

To export data from SQL Server to Excel, right-click the SSMS results grid and choose Save Results As (SSMS 22.4.1+ saves .xlsx), or script it with bcp, sqlcmd or PowerShell.

The catch is Excel: it turns ZIP code 02118 into 2118 when it opens a CSV. I’ll show which exports kept the zero.

Tested on SQL Server 2025 (17.0.1000.7) Developer, bcp 15.0, PowerShell 7.6.

The Sample Customers Table We’ll Export to Excel

Watch Tyler Reed, Jr. (a comma), Zoë Turner (an accent) and the ZIPs starting with 0.

CREATE TABLE dbo.Customers (
    CustomerID int           PRIMARY KEY,
    FullName   nvarchar(20)  NOT NULL,
    ZipCode    char(5)       NOT NULL,
    SignupDate date          NOT NULL,
    Balance    decimal(10,2) NOT NULL
);
INSERT INTO dbo.Customers VALUES
(1, N'Hannah Brooks',   '02118', '2026-01-14', 1250.00),
(2, N'Tyler Reed, Jr.', '07102', '2026-02-03',   89.50),
(3, N'Zoë Turner',      '78701', '2026-03-22',  410.75),
(4, N'Marcus Bennett',  '04101', '2026-05-09',    0.00),
(5, N'Grace Miller',    '80202', '2026-06-30', 2310.40);

Check your work with SELECT * FROM dbo.Customers;. You should see five rows.

Method 1: Copy or Save the SSMS Results Grid (Recommended for One-Off Exports)

Run your query in SSMS (free, see how to install SSMS), then:

  1. Right-click the grid, choose Copy with Headers (Ctrl+Shift+C), and paste into cell A1.
  2. Or choose Save Results As. SSMS 22.4.1 (March 2026) added Excel; older versions save CSV or text.
  3. In SSMS 22.10.2+, tick the include-column-headers box in that dialog.

How does this work? Copy puts tab-separated text on the clipboard. Excel still guesses types on paste, so format column C as Text first.

Method 2: SQL Server Import and Export Wizard to an Excel File

The wizard writes a real .xlsx. The steps, per Microsoft Learn:

  1. Right-click the database, then Tasks > Export Data.
  2. On Choose a Destination, pick Microsoft Excel, a file path and Excel version Microsoft Excel 2016. Keep First row has column names.
  3. Choose Copy data from one or more tables or views or Write a query, select dbo.Customers, then Finish.

Important: since SSMS 21 and SQL Server 2025 the wizard is 64-bit only. It needs Microsoft.ACE.OLEDB.16.0 from the Access Database Engine 2016 Redistributable.

How does this work? Older SSMS ran a 32-bit wizard that couldn’t see 64-bit providers, which is why Excel vanished from the list for so many people. On my PC, EXEC master.dbo.sp_enum_oledb_providers; listed ACE 12.0 and 16.0.

Method 3: Get Data From SQL Server Database in Excel

For a sheet that refreshes, use Data > Get Data > From Database > From SQL Server Database, enter localhost and DfExcelExport, pick dbo.Customers, Load.

How does this work? Excel keeps a Power Query connection to the same table, so Refresh All reruns it, the way you’d connect Excel to an Oracle database.

Method 4: bcp queryout to a CSV File

bcp is what I’d script for big tables. It has no header option, so echo one first:

@echo off
chcp 65001 >nul
echo CustomerID,FullName,ZipCode,SignupDate,Balance> customers-bcp.csv
bcp "SELECT CustomerID, FullName, ZipCode, SignupDate, Balance FROM dbo.Customers" queryout rows.csv -c -C 65001 -t, -S localhost -T -d DfExcelExport
type rows.csv >> customers-bcp.csv
del rows.csv
type customers-bcp.csv

Output:


Starting copy...

5 rows copied.
Network packet size (bytes): 4096
Clock Time (ms.) Total     : 1      Average : (5000.00 rows per sec.)
CustomerID,FullName,ZipCode,SignupDate,Balance
1,Hannah Brooks,02118,2026-01-14,1250.00
2,Tyler Reed, Jr.,07102,2026-02-03,89.50
3,Zoë Turner,78701,2026-03-22,410.75
4,Marcus Bennett,04101,2026-05-09,.00
5,Grace Miller,80202,2026-06-30,2310.40
SQL Server bcp queryout export to CSV with a header row, -c -C 65001 -t comma options
The comma splits Tyler’s row

How does this work? -c writes text, -t, sets the comma, -T uses Windows login, -C 65001 writes UTF-8. Clock Time stayed under 20 ms for five rows in every run.

Two catches: bcp doesn’t quote fields, so Tyler’s row has six values, and 0.00 came out as .00. BULK INSERT reads the file back.

Method 5: sqlcmd -s and -W for a Quick CSV

sqlcmd writes the header for you. Same query:

@echo off
chcp 65001 >nul
sqlcmd -S localhost -E -C -d DfExcelExport -s"," -W -f o:65001 -o customers-sqlcmd.csv ^
  -Q "SET NOCOUNT ON; SELECT CustomerID, FullName, ZipCode, SignupDate, Balance FROM dbo.Customers"
type customers-sqlcmd.csv

Output:

CustomerID,FullName,ZipCode,SignupDate,Balance
----------,--------,-------,----------,-------
1,Hannah Brooks,02118,2026-01-14,1250.00
2,Tyler Reed, Jr.,07102,2026-02-03,89.50
3,Zoë Turner,78701,2026-03-22,410.75
4,Marcus Bennett,04101,2026-05-09,.00
5,Grace Miller,80202,2026-06-30,2310.40
sqlcmd -s comma -W export of SQL Server query results to CSV with a dashes line under the header
The dashes line stays

How does this work? -s"," sets the separator, -W trims padding, -f o:65001 writes UTF-8 with a BOM. The dashes line becomes Excel row 2; -h -1 drops both header lines.

Method 6: PowerShell Invoke-Sqlcmd to CSV or a Real .xlsx

I already had the SqlServer and ImportExcel modules (Get-Module -ListAvailable shows yours):

Import-Module SqlServer, ImportExcel
$rows = Invoke-Sqlcmd -ServerInstance localhost -Database DfExcelExport `
  -TrustServerCertificate -Query "SELECT CustomerID, FullName, ZipCode,
  CONVERT(char(10), SignupDate, 23) AS SignupDate, Balance FROM dbo.Customers" |
  Select-Object CustomerID, FullName, ZipCode, SignupDate, Balance
$rows | Export-Csv customers-ps.csv -NoTypeInformation -Encoding utf8BOM
$rows | Export-Excel customers.xlsx -WorksheetName Customers `
  -NoNumberConversion ZipCode -AutoSize
Get-Content customers-ps.csv

Output:

"CustomerID","FullName","ZipCode","SignupDate","Balance"
"1","Hannah Brooks","02118","2026-01-14","1250.00"
"2","Tyler Reed, Jr.","07102","2026-02-03","89.50"
"3","Zoë Turner","78701","2026-03-22","410.75"
"4","Marcus Bennett","04101","2026-05-09","0.00"
"5","Grace Miller","80202","2026-06-30","2310.40"
PowerShell Invoke-Sqlcmd piped to Export-Csv and Export-Excel, exporting SQL Server data to CSV and xlsx
Every field quoted

How does this work? Export-Csv quotes fields, so Tyler stays in one cell. Export-Excel writes the .xlsx, and -NoNumberConversion ZipCode keeps ZIPs as text.

Important: without the CONVERT, my dates came out in the PC’s regional format plus 00:00:00 (see convert a datetime to a string).

Why Does Excel Drop Leading Zeros When It Opens a CSV?

I opened the files through Excel’s COM object, with no window, and read the cells:

$xl = New-Object -ComObject Excel.Application
foreach ($f in 'customers-bcp.csv', 'customers-ps.csv', 'customers.xlsx') {
  $ws = $xl.Workbooks.Open((Join-Path $PWD $f)).Worksheets(1)
  '{0,-18} B3={1,-16} C2={2,-6} D2={3,-6} B4={4}' -f $f,
    $ws.Range('B3').Text, $ws.Range('C2').Value2,
    $ws.Range('D2').Value2, $ws.Range('B4').Text
  $ws.Parent.Close($false)
}
$xl.Quit()

What Excel stored:

customers-bcp.csv  B3=Tyler Reed       C2=2118   D2=46036  B4=Zoë Turner
customers-ps.csv   B3=Tyler Reed, Jr.  C2=2118   D2=46036  B4=Zoë Turner
customers.xlsx     B3=Tyler Reed, Jr.  C2=02118  D2=2026-01-14 B4=Zoë Turner
Excel opening CSV files from SQL Server drops leading zeros in ZIP codes while the xlsx keeps 02118
Only the .xlsx kept 02118

Both CSVs gave 2118, and D2 became 46036, the serial for 01/14/2026. The bcp file had no BOM, so Zoë became Zoë.

For a CSV, use Data > From Text/CSV and set ZipCode to Text; for dates see SQL Server date format.

Export Data From SQL Server to Excel Automatically

Schedule export-powershell.ps1 with Task Scheduler or an Agent CmdExec step (if Agent won’t start).

Skip ACE there: Microsoft doesn’t support it unattended, which rules out OPENROWSET(‘Microsoft.ACE.OLEDB.16.0’, …). That also needs Ad Hoc Distributed Queries enabled, which I left off.

Which Export Method to Pick, and Things to Keep in Mind

MethodWritesBest for
SSMS grid.xlsx, CSVOne-off
Wizard.xlsxWhole tables
Excel Get DataLive tableRefreshing reports
bcp / sqlcmdCSVBig or scripted dumps
PowerShellCSV, .xlsxSchedules, text kept
  • bcp writes no header or quotes; use -t"|" for free text.
  • bcp -c uses the OEM code page unless you add -C 65001; -w writes UTF-16.
  • A worksheet holds 1,048,576 rows.

Next step: on Postgres, read PostgreSQL export table to CSV.

Frequently Asked Questions

How do I always copy SSMS results with column headers?

Check Include column headers when copying or saving the results under Tools > Options > Query Results > SQL Server > Results to Grid.

Does bcp work with Azure SQL Database?

Yes, but -T isn’t supported; use -G for Microsoft Entra ID, per the bcp utility docs.

Why is long text cut at 255 characters in a wizard export?

The Excel driver treats text as 255-character strings unless a sampled row is longer. PowerShell avoids that.