C'è un modo per eseguire una query arbitraria su un SQL Server usando Powershell sul mio computer locale?
C'è un modo per eseguire una query arbitraria su un SQL Server usando Powershell sul mio computer locale?
Risposte:
Per gli altri che hanno bisogno di farlo con solo stock .net e PowerShell (non sono installati ulteriori strumenti SQL) ecco la funzione che uso:
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
}
Lo sto usando da così tanto tempo che non so chi abbia scritto quali parti, ma questo è stato distillato dagli esempi di altri ma semplificato per essere chiaro e solo ciò che è necessario senza dipendenze o funzionalità extra.
Lo uso e lo condivido abbastanza spesso da averlo trasformato in un modulo di script su GitHub in modo da poter ora andare alla directory dei moduli ed eseguirlo git clone https://github.com/ChrisMagnuson/InvokeSQL
e da quel momento in poi invoke-sql verrà automaticamente caricato quando si andrà a usarlo (supponendo stai usando PowerShell v3 o successivo).
$connection.dispose()
ecc. Non so se fa alcuna differenza
È possibile utilizzare il Invoke-Sqlcmd
cmdlet
Invoke-Sqlcmd -Query "SELECT GETDATE() AS TimeOfQuery;" -ServerInstance "MyComputer\MyInstance"
Import-Module "sqlps" -DisableNameChecking
Ecco un esempio che ho trovato su questo blog .
$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();
Presumibilmente potresti sostituire una diversa istruzione TSQL dove dice dbcc freeproccache
.
ExecuteNonQuery()
è tornato a zero in caso di successo, la condizione che l'uso io è: if ($cmd.ExecuteNonQuery() -ne 0)
.
Questa funzione restituirà i risultati di una query come una matrice di oggetti PowerShell in modo da poterli utilizzare nei filtri e accedere facilmente alle colonne:
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
(vedi la risposta di Adamo )?
Se vuoi farlo sul tuo computer locale invece che nel contesto di SQL Server, userò quanto segue. È quello che usiamo nella mia azienda.
$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
Basta compilare le variabili $ ServerName , $ DatabaseName e $ Query e dovresti essere pronto.
Io non sono sicuro di come abbiamo inizialmente trovato questo fuori, ma c'è qualcosa di molto simile qui .
Invoke-Sqlcmd -Query "sp_who" -ServerInstance . -QueryTimeout 3
Non esiste un modo "PowerShell" incorporato per eseguire una query SQL. Se hai installato gli strumenti di SQL Server , otterrai un cmdlet Invoke-SqlCmd .
Poiché PowerShell è basato su .NET, è possibile utilizzare l' API ADO.NET per eseguire le query.
Per evitare l'iniezione SQL con i parametri varchar è possibile utilizzare
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