¿Hay alguna manera de ejecutar una consulta arbitraria en un servidor SQL utilizando Powershell en mi máquina local?
¿Hay alguna manera de ejecutar una consulta arbitraria en un servidor SQL utilizando Powershell en mi máquina local?
Respuestas:
Para otros que necesitan hacer esto solo con stock .net y PowerShell (sin herramientas SQL adicionales instaladas), esta es la función que 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
}
He estado usando esto durante tanto tiempo que no sé quién escribió qué partes, pero esto se destiló de los ejemplos de otros, pero se simplificó para ser claro y lo que se necesita sin dependencias o características adicionales.
Utilizo y comparto esto con suficiente frecuencia que lo he convertido en un módulo de script en GitHub para que ahora pueda ir al directorio de módulos y ejecutarlo git clone https://github.com/ChrisMagnuson/InvokeSQL
y, a partir de ese momento, invoke-sql se cargará automáticamente cuando vaya a usarlo (suponiendo estás usando powershell v3 o posterior).
$connection.dispose()
etc. No sé si hace alguna diferencia
Puedes usar el Invoke-Sqlcmd
cmdlet
Invoke-Sqlcmd -Query "SELECT GETDATE() AS TimeOfQuery;" -ServerInstance "MyComputer\MyInstance"
Import-Module "sqlps" -DisableNameChecking
Aquí hay un ejemplo que encontré en este 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();
Presumiblemente, podría sustituir una declaración TSQL diferente donde dice dbcc freeproccache
.
ExecuteNonQuery()
devuelve cero en caso de éxito, la condición de que el uso que es: if ($cmd.ExecuteNonQuery() -ne 0)
.
Esta función devolverá los resultados de una consulta como una matriz de objetos de PowerShell para que pueda usarlos en filtros y acceder a columnas fácilmente:
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
(ver la respuesta de Adam )?
Si desea hacerlo en su máquina local en lugar de hacerlo en el contexto del servidor SQL, usaría lo siguiente. Es lo que usamos en mi empresa.
$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
Simplemente complete las variables $ ServerName , $ DatabaseName y $ Query y estará listo.
No estoy seguro de cómo nos encontramos originalmente esto, pero hay algo muy similar aquí .
No hay una forma integrada de "PowerShell" de ejecutar una consulta SQL. Si tiene instaladas las herramientas de SQL Server , obtendrá un cmdlet Invoke-SqlCmd .
Debido a que PowerShell está construido en .NET, puede usar la API ADO.NET para ejecutar sus consultas.
Para evitar la inyección SQL con parámetros varchar, puede usar
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