Recently I went through requirement of running SQL scripts on multiple databases on different servers. As the list of databases was different from script to script I decided to create universal solution, which will allow to easily prepare for deployment and can be simply reused at any time.

As a platform to execute scripts I went with PowerShell as that provides flexibility in case additional functionality will be required.

Whole solution contains 3 files:

  • SqlExecutionInflow.csv – file contains list of databases and servers where particular database is located. It is simple CSV file with 2 columns
  • SqlExecQuery.sql – contains SQL script which will be executed against all databases listed in SqlExecutionInflow.csv
  • SqlExec.ps1 – main script which load SqlExecInflow.csv and executes query from SqlExecQuery.sql

All files have to be placed in same folder. As a result script will create transcript file with output from all executed commands.

And here are example files and script itself…

SqlExecInflow.csv

DBname,DBserver
AdventureWorksDB,SQL-SERVER-01
Northwind,SQL-SERVER-01

SqlExecQuery.sql

SELECT @@VERSION

SqlExec.ps1

Import-Module SqlPs

# Load Smo and referenced assemblies.
[void][System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.ConnectionInfo');
[void][System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.Management.Sdk.Sfc');
[void][System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO');
# Requiered for SQL Server 2008 (SMO 10.0).
[void][System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMOExtended');

# Determine script location for PowerShell
$ScriptDir = Split-Path $script:MyInvocation.MyCommand.Path

$SqlExecInflowList = $ScriptDir + "\SqlExecInflow.csv"
$SqlExecOutputLog = $ScriptDir + "\SqlExecOutput.log"
$SqlExecQueryFile = $ScriptDir + "\SqlExecQuery.sql"

$DatabaseListArray = @()
$DatabaseListArray = Import-CSV $SqlExecInflowList

Start-Transcript $SqlExecOutputLog

foreach ($DatabaseItem in $DatabaseListArray)
{
$DatabaseName = $DatabaseItem.DBname
$DatabaseServer = $DatabaseItem.DBserver

Invoke-SqlCmd -InputFile $SqlExecQueryFile -ServerInstance $DatabaseServer -Database $DatabaseName -Verbose
}

Stop-Transcript