简体   繁体   中英

Export SQL data to Excel - Best possible approach?

I am currently working on an automation which requires to export sql results to excel data. I want to do this via SQL query. Few options i know are as below, but before i start exploring these things. I would like to know the best possible approach .

PS - It would be really great if there is a way to dynamically create excel during query execution and export data in multiple excel sheets.

  1. OPENROWSET
  2. bcp_cmd

You can CREATE VIEW and utilize that view in Excel 2016 under its data connections through PowerQuery . Views are preferred since they are managed independently in the server, and provide realtime data results without requiring a full query to be embedded in the Excel file. The resulting set exists in the workbook as a refresh-able table. Results that need to be recorded should be done via new workbooks or UPDATE 's back to the server in a separate script.

在此处输入图片说明

In the PowerQuery Editor, Home tab, click Advanced Editor . The database connection string and call to the server is below. You can also dynamically pass parameters from an Excel table to the query utilizing a table in the Name Manager .

Excel tab, table name: tbl_Parameters

    A         B
1 StartDate  01/01/2020
2 EndDate    02/01/2020
let
   Source = Sql.Database("ServerName" , "Database", [Query="

DECLARE @Start_Date AS datetime
DECLARE @End_Date AS datetime

SET @Start_Date = '"&StartDate&"'
SET @End_Date = '"&EndDate&"'


SELECT * FROM uvw_product
WHERE item_sold_date BETWEEN
@Start_Date AND @End_Date

"])
in
   Source

A while back I cobbled this Powershell script together.
It querys sql server data, saves as csv, formats it and saves as xls, then mails via smtp.
You can set up a windows scheduled task to automate it.

There's also an import xls module for powershell.

Import-Module Sqlps -DisableNameChecking;

#execute mysql query as excel
$Server = "DB SERVER";
$Database = "DBNAME";

$Query = @"
*SELECT QUERY HERE*
"@
$a = Get-Date
#note: if you run get-location from ide, it will use the ide path instead of the script path 
$currentLocation = Split-Path -Parent $PSCommandPath
$FilePath = $currentLocation + "\CSVName.csv"
$SavePath = $currentLocation + "\XLSFileName" +$a.Day+ $a.Month + $a.Year + ".xls"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $Server; Database = $Database; User ID = DBUSERNAME; Password = PASSWORD";
$SqlConnection.Open()
$sqlcmd = $SqlConnection.CreateCommand()
$sqlcmd.Connection = $SqlConnection
$sqlcmd.CommandText = $Query


$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $sqlcmd
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$DataSet.Tables[0] | Export-Csv -notypeinformation $FilePath


$SqlConnection.Close()
#Invoke-Sqlcmd -Query $Query -ConnectionString $SqlConnection.ConnectionString | Export-Csv -notypeinformation $FilePath

#release memory function
function Release-Ref($ref){
    ([System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$ref) -gt 0)
    [System.GC]::Collect()
    [System.GC]::WaitForPendingFinalizers()
}

#format excel to display correct date
$objExcel = new-object -comobject excel.application  
$objWorkbook = $objExcel.Workbooks.open($FilePath)
$objWorksheet = $objWorkbook.Worksheets.Item(1) 
$objRange = $objWorksheet.UsedRange
[void] $objRange.EntireColumn.Autofit()
$objWorkbook.Saved = $True
$objExcel.DisplayAlerts = $False
$objWorkbook.SaveAs($SavePath,1)
$objExcel.Quit()

#release memory
Release-Ref($objWorksheet) 
Release-Ref($objWorkbook) 
Release-Ref($objExcel)

#create mail
$smtpServer = "SMTPSERVER"
$smtp = new-object Net.Mail.SmtpClient($smtpServer)

$att = new-object Net.Mail.Attachment($SavePath)
$msg = new-object Net.Mail.MailMessage
$msg.Subject = "EMAIL SUBJECT"
$msg.From = "FROM EMAIL"
#$msg.To.Add("TO EMAIL 1")
$msg.To.Add("TO EMAIL 2")
$msg.Body = @"
Hi,

MSG BODY HERE

Best Regards
"@
$msg.Attachments.Add($att)

$smtp.Send($msg)
$att.Dispose()

Download and install the 64-bit or 32-bit version of the driver, based on what you have installed.

https://www.microsoft.com/en-us/download/details.aspx?id=13255

Then, you should be able to run this.

insert into OPENROWSET('Microsoft.Jet.OLEDB.4.0', 
    'Excel 8.0;Database=D:\testing.xls;', 
    'SELECT * FROM [SheetName$]') select * from SQLServerTable

Notice: this may not work if you have one 32-bit technology and one 64-bit technology. In this case, you may need to employ some kind of workaround.

See this link for additional ideas of how to integrate SQL Server and Excel.

https://solutioncenter.apexsql.com/how-to-import-and-export-sql-server-data-to-an-excel-file/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM