Есть ли способ выполнить произвольный запрос на SQL Server, используя Powershell на моем локальном компьютере?
Есть ли способ выполнить произвольный запрос на SQL Server, используя Powershell на моем локальном компьютере?
Ответы:
Для других, которым нужно сделать это с помощью только стандартных .net и PowerShell (без дополнительных инструментов SQL), вот функция, которую я использую:
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
}
Я использовал это так долго, что я не знаю, кто написал, какие части, но это было извлечено из других примеров, но упрощено, чтобы быть ясным и просто то, что нужно без дополнительных зависимостей или функций.
Я использую и делюсь этим достаточно часто, чтобы превратить это в модуль сценариев на GitHub, чтобы вы теперь могли перейти в каталог модулей и выполнить его, git clone https://github.com/ChrisMagnuson/InvokeSQL
и с этого момента invoke-sql будет автоматически загружаться при его использовании (при условии, что вы используете powershell v3 или новее).
$connection.dispose()
и т. Д. Я не знаю, имеет ли это какое-то значение
Вы можете использовать Invoke-Sqlcmd
командлет
Invoke-Sqlcmd -Query "SELECT GETDATE() AS TimeOfQuery;" -ServerInstance "MyComputer\MyInstance"
Import-Module "sqlps" -DisableNameChecking
Вот пример, который я нашел в этом блоге .
$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();
Предположительно, вы можете заменить другой оператор TSQL там, где он написан dbcc freeproccache
.
ExecuteNonQuery()
вернулся к нулю в случае успеха, условие , что использование I является: if ($cmd.ExecuteNonQuery() -ne 0)
.
Эта функция возвращает результаты запроса в виде массива объектов PowerShell, так что вы можете использовать их в фильтрах и легко получать доступ к столбцам:
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
(см . Ответ Адама )?
Если вы хотите сделать это на локальном компьютере, а не в контексте SQL-сервера, я бы использовал следующее. Это то, что мы используем в моей компании.
$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
Просто заполните переменные $ ServerName , $ DatabaseName и $ Query, и все будет хорошо.
Я не знаю , как мы первоначально обнаружили это, но есть что - то очень похоже здесь .
Не существует встроенного способа «PowerShell» для выполнения SQL-запроса. Если у вас установлены инструменты SQL Server , вы получите командлет Invoke-SqlCmd .
Поскольку PowerShell построен на .NET, вы можете использовать API ADO.NET для выполнения ваших запросов.
Чтобы избежать SQL-инъекций с параметрами varchar, вы можете использовать
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