Welcome PowerShell User! This recipe is just one of the hundreds of useful resources contained in the PowerShell Cookbook.
If you own the book already, login here to get free, online, searchable access to the entire book's content.
If not, the Windows PowerShell Cookbook is available at Amazon, or any of your other favourite book retailers. If you want to see what the PowerShell Cookbook has to offer, enjoy this free 90 page e-book sample: "The Windows PowerShell Interactive Shell".
It’s often helpful to perform ad hoc queries and commands against a data source such as a SQL server, Access database, or even an Excel spreadsheet. This is especially true when you want to take data from one system and put it in another, or when you want to bring the data into your PowerShell environment for detailed interactive manipulation or processing.
Although you can directly access each of these data sources in PowerShell (through its support of the .NET Framework), each data source requires a unique and hard-to-remember syntax. Example 17-1 makes working with these SQL-based data sources both consistent and powerful.
##############################################################################
##
## Invoke-SqlCommand
##
## From PowerShell Cookbook (O'Reilly)
## by Lee Holmes (http://www.leeholmes.com/guide)
##
##############################################################################
<#
.SYNOPSIS
Return the results of a SQL query or operation
.EXAMPLE
Invoke-SqlCommand.ps1 -Sql "SELECT TOP 10 * FROM Orders"
Invokes a command using Windows authentication
.EXAMPLE
PS > $cred = Get-Credential
PS > Invoke-SqlCommand.ps1 -Sql "SELECT TOP 10 * FROM Orders" -Cred $cred
Invokes a command using SQL Authentication
.EXAMPLE
PS > $server = "MYSERVER"
PS > $database = "Master"
PS > $sql = "UPDATE Orders SET EmployeeID = 6 WHERE OrderID = 10248"
PS > Invoke-SqlCommand $server $database $sql
Invokes a command that performs an update
.EXAMPLE
PS > $sql = "EXEC SalesByCategory 'Beverages'"
PS > Invoke-SqlCommand -Sql $sql
Invokes a stored procedure
.EXAMPLE
PS > Invoke-SqlCommand (Resolve-Path access_test.mdb) -Sql "SELECT * FROM Users"
Access an Access database
.EXAMPLE
PS > Invoke-SqlCommand (Resolve-Path xls_test.xls) -Sql 'SELECT * FROM [Sheet1$]'
Access an Excel file
#>
param
(
## The data source to use in the connection
[string]
$DataSource
=
".\SQLEXPRESS"
,
## The database within the data source
[string]
$Database
=
"Northwind"
,
## The SQL statement(s) to invoke against the database
[
Parameter
(
Mandatory
=
$true
)]
[string[]]
$SqlCommand
,
## The timeout, in seconds, to wait for the query to complete
[int]
$Timeout
=
60
,
## The credential to use in the connection, if any.
$Credential
)
Set-StrictMode
-Version
3
## Prepare the authentication information. By default, we pick
## Windows authentication
$authentication
=
"Integrated Security=SSPI;"
## If the user supplies a credential, then they want SQL
## authentication
if
(
$credential
)
{
$credential
=
Get-Credential
$credential
$plainCred
=
$credential
.
GetNetworkCredential
()
$authentication
=
(
"uid={0};pwd={1};"
-f
$plainCred
.
Username
,
$plainCred
.
Password
)
}
## Prepare the connection string out of the information they
## provide
$connectionString
=
"Provider=sqloledb; "
+
"Data Source=$dataSource; "
+
"Initial Catalog=$database; "
+
"$authentication; "
## If they specify an Access database or Excel file as the connection
## source, modify the connection string to connect to that data source
if
(
$dataSource
-match
'\.xls$|\.mdb$'
)
{
$connectionString
=
"Provider=Microsoft.Jet.OLEDB.4.0; "
+
"Data Source=$dataSource; "
if
(
$dataSource
-match
'\.xls$'
)
{
$connectionString
+=
'Extended Properties="Excel 8.0;"; '
## Generate an error if they didn't specify the sheet name properly
if
(
$sqlCommand
-notmatch
'\[.+\$\]'
)
{
$error
=
'Sheet names should be surrounded by square brackets, '
+
'and have a dollar sign at the end: [Sheet1$]'
Write-Error
$error
return
}
}
}
## Connect to the data source and open it
$connection
=
New-Object
System
.
Data
.
OleDb
.
OleDbConnection
$connectionString
$connection
.
Open
()
foreach
(
$commandString
in
$sqlCommand
)
{
$command
=
New-Object
Data
.
OleDb
.
OleDbCommand
$commandString
,
$connection
$command
.
CommandTimeout
=
$timeout
## Fetch the results, and close the connection
$adapter
=
New-Object
System
.
Data
.
OleDb
.
OleDbDataAdapter
$command
$dataset
=
New-Object
System
.
Data
.
DataSet
[void]
$adapter
.
Fill
(
$dataSet
)
## Return all of the rows from their query
$dataSet
.
Tables
|
Select-Object
-Expand
Rows
}
$connection
.
Close
()
For more information about running scripts, see Recipe 1.2.
Recipe 1.2, “Run Programs, Scripts, and Existing Tools”