Existe-t-il un moyen d'exécuter une requête arbitraire sur un serveur SQL à l'aide de Powershell sur ma machine locale?
Existe-t-il un moyen d'exécuter une requête arbitraire sur un serveur SQL à l'aide de Powershell sur ma machine locale?
Réponses:
Pour les autres qui ont besoin de le faire avec juste du stock .net et PowerShell (aucun outil SQL supplémentaire installé), voici la fonction que j'utilise:
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
}
J'utilise ceci depuis si longtemps que je ne sais pas qui a écrit quelles parties, mais cela a été distillé à partir d'exemples d'autres mais simplifié pour être clair et juste ce qui est nécessaire sans dépendances ou fonctionnalités supplémentaires.
J'utilise et partage cela assez souvent pour que je l'ai transformé en un module de script sur GitHub afin que vous puissiez maintenant aller dans votre répertoire de modules et l'exécuter git clone https://github.com/ChrisMagnuson/InvokeSQL
et à partir de ce moment, invoke-sql sera automatiquement chargé lorsque vous l'utiliserez (en supposant votre utilisation de PowerShell v3 ou version ultérieure).
$connection.dispose()
etc. Je ne sais pas si cela fait une différence
Vous pouvez utiliser l' Invoke-Sqlcmd
applet de commande
Invoke-Sqlcmd -Query "SELECT GETDATE() AS TimeOfQuery;" -ServerInstance "MyComputer\MyInstance"
Import-Module "sqlps" -DisableNameChecking
Voici un exemple que j'ai trouvé sur ce 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();
Vraisemblablement, vous pouvez remplacer une instruction TSQL différente là où elle est indiquée dbcc freeproccache
.
ExecuteNonQuery()
revenu à zéro en cas de succès, à condition que je utiliser est: if ($cmd.ExecuteNonQuery() -ne 0)
.
Cette fonction retournera les résultats d'une requête sous forme de tableau d'objets PowerShell afin que vous puissiez les utiliser dans des filtres et accéder facilement aux colonnes:
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
(voir la réponse d'Adam )?
Si vous voulez le faire sur votre machine locale au lieu de dans le contexte du serveur SQL, j'utiliserais ce qui suit. C'est ce que nous utilisons dans mon entreprise.
$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
Remplissez simplement $ ServerName , $ DatabaseName et $ Query variables et vous devriez être prêt à partir.
Je ne sais pas comment nous l'avons découvert à l'origine, mais il y a quelque chose de très similaire ici .
Il n'existe pas de méthode "PowerShell" intégrée pour exécuter une requête SQL. Si vous avez installé les outils SQL Server , vous obtiendrez un Invoke-SqlCmd cmdlet .
Étant donné que PowerShell est basé sur .NET, vous pouvez utiliser l' API ADO.NET pour exécuter vos requêtes.
Pour éviter l'injection SQL avec des paramètres varchar, vous pouvez utiliser
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