Czy istnieje sposób wykonania dowolnego zapytania na serwerze SQL przy użyciu programu PowerShell na moim komputerze lokalnym?
Czy istnieje sposób wykonania dowolnego zapytania na serwerze SQL przy użyciu programu PowerShell na moim komputerze lokalnym?
Odpowiedzi:
Dla innych, którzy muszą to zrobić za pomocą zwykłego .net i PowerShell (bez zainstalowanych dodatkowych narzędzi SQL), oto funkcja, której używam:
function Invoke-SQL {
param(
[string] $dataSource = ".\SQLEXPRESS",
[string] $database = "MasterData",
[string] $sqlCommand = $(throw "Please specify a query.")
)
$connectionString = "Data Source=$dataSource; " +
"Integrated Security=SSPI; " +
"Initial Catalog=$database"
$connection = new-object system.data.SqlClient.SQLConnection($connectionString)
$command = new-object system.data.sqlclient.sqlcommand($sqlCommand,$connection)
$connection.Open()
$adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
$dataset = New-Object System.Data.DataSet
$adapter.Fill($dataSet) | Out-Null
$connection.Close()
$dataSet.Tables
}
Używam tego od tak dawna, że nie wiem, kto napisał, które części, ale zostało to wydestylowane z przykładów innych, ale uproszczone, aby było jasne i tylko to, co jest potrzebne, bez dodatkowych zależności lub funkcji.
Używam i udostępniam to na tyle często, że zamieniłem to w moduł skryptu na GitHub , abyś mógł teraz przejść do katalogu modułów i wykonać, git clone https://github.com/ChrisMagnuson/InvokeSQL
a od tego momentu invoke-sql zostanie automatycznie załadowany, gdy zaczniesz go używać (zakładając korzystasz z PowerShell w wersji 3 lub nowszej).
$connection.dispose()
itp. Nie wiem, czy to robi jakąkolwiek różnicę
Możesz użyć polecenia Invoke-Sqlcmd
cmdlet
Invoke-Sqlcmd -Query "SELECT GETDATE() AS TimeOfQuery;" -ServerInstance "MyComputer\MyInstance"
Import-Module "sqlps" -DisableNameChecking
Oto przykład, który znalazłem na tym blogu .
$cn2 = new-object system.data.SqlClient.SQLConnection("Data Source=machine1;Integrated Security=SSPI;Initial Catalog=master");
$cmd = new-object system.data.sqlclient.sqlcommand("dbcc freeproccache", $cn2);
$cn2.Open();
if ($cmd.ExecuteNonQuery() -ne -1)
{
echo "Failed";
}
$cn2.Close();
Przypuszczalnie można by zastąpić inną instrukcję TSQL tam, gdzie jest napisana dbcc freeproccache
.
ExecuteNonQuery()
wrócił do zera w przypadku sukcesu, warunek, że używam to: if ($cmd.ExecuteNonQuery() -ne 0)
.
Ta funkcja zwróci wyniki zapytania jako tablicę obiektów PowerShell, dzięki czemu można ich używać w filtrach i łatwo uzyskiwać dostęp do kolumn:
function sql($sqlText, $database = "master", $server = ".")
{
$connection = new-object System.Data.SqlClient.SQLConnection("Data Source=$server;Integrated Security=SSPI;Initial Catalog=$database");
$cmd = new-object System.Data.SqlClient.SqlCommand($sqlText, $connection);
$connection.Open();
$reader = $cmd.ExecuteReader()
$results = @()
while ($reader.Read())
{
$row = @{}
for ($i = 0; $i -lt $reader.FieldCount; $i++)
{
$row[$reader.GetName($i)] = $reader.GetValue($i)
}
$results += new-object psobject -property $row
}
$connection.Close();
$results
}
DataTable
(patrz odpowiedź Adama )?
Jeśli chcesz to zrobić na komputerze lokalnym, a nie w kontekście serwera SQL, użyłbym następującego. To jest to, czego używamy w mojej firmie.
$ServerName = "_ServerName_"
$DatabaseName = "_DatabaseName_"
$Query = "SELECT * FROM Table WHERE Column = ''"
#Timeout parameters
$QueryTimeout = 120
$ConnectionTimeout = 30
#Action of connecting to the Database and executing the query and returning results if there were any.
$conn=New-Object System.Data.SqlClient.SQLConnection
$ConnectionString = "Server={0};Database={1};Integrated Security=True;Connect Timeout={2}" -f $ServerName,$DatabaseName,$ConnectionTimeout
$conn.ConnectionString=$ConnectionString
$conn.Open()
$cmd=New-Object system.Data.SqlClient.SqlCommand($Query,$conn)
$cmd.CommandTimeout=$QueryTimeout
$ds=New-Object system.Data.DataSet
$da=New-Object system.Data.SqlClient.SqlDataAdapter($cmd)
[void]$da.fill($ds)
$conn.Close()
$ds.Tables
Wystarczy wypełnić zmienne $ ServerName , $ DatabaseName i $ Query i wszystko powinno być gotowe.
Nie jestem pewien, jak pierwotnie znaleźć na to uwagę, ale jest coś bardzo podobnego tutaj .
Nie ma wbudowanego „PowerShell” sposobu uruchamiania zapytania SQL. Jeśli masz zainstalowane narzędzia SQL Server , otrzymasz polecenie cmdlet Invoke-SqlCmd .
Ponieważ program PowerShell jest oparty na platformie .NET, do uruchamiania zapytań można używać interfejsu API ADO.NET .
Aby uniknąć iniekcji SQL z parametrami varchar, możesz użyć
function sqlExecuteRead($connectionString, $sqlCommand, $pars) {
$connection = new-object system.data.SqlClient.SQLConnection($connectionString)
$connection.Open()
$command = new-object system.data.sqlclient.sqlcommand($sqlCommand, $connection)
if ($pars -and $pars.Keys) {
foreach($key in $pars.keys) {
# avoid injection in varchar parameters
$par = $command.Parameters.Add("@$key", [system.data.SqlDbType]::VarChar, 512);
$par.Value = $pars[$key];
}
}
$adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
$dataset = New-Object System.Data.DataSet
$adapter.Fill($dataset) | Out-Null
$connection.Close()
return $dataset.tables[0].rows
}
$connectionString = "..."
$sql = "select top 10 Message, TimeStamp, Level from dbo.log "+
"where Message = @MSG and Level like @LEVEL ";
$pars = @{
MSG = 'this is a test from powershell';
LEVEL = 'aaa%';
};
sqlExecuteRead $connectionString $sql $pars