PowerShellからSQL Serverクエリをどのように実行しますか?


161

ローカルマシンのPowershellを使用してSQL Serverで任意のクエリを実行する方法はありますか?

回答:


166

純正の.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以降を使用している場合)。


ここまたはPowerShellで廃棄は問題ではありませんか?
マズロー2014年

2
@Maslow確かに言えませんでしたが、オブジェクトを破棄せずにこれが正常に機能することはわかっていますが、これを閉じずに数週間にわたってこれを複数回呼び出す単一のpowershell.exeプロセスがある場合、最終的に問題になる可能性がありますが、それをテストする必要があります。
Chris Magnuson

1
ユーザー入力に依存するソースからクエリのデータを読み取ることに依存している場合、SQLインジェクション攻撃に対して脆弱である可能性があるスクリプトを作成する必要があることに注意してください。
Joel Coehoorn 14年

4
@AllTradesJack Google Sqlインジェクション。Invoke-Sqlコマンドには、コマンドテキストとは別のパラメーターを含める方法がありません。これにより、文字列連結を使用してクエリを構築することがほぼ保証されます。
Joel Coehoorn 2017年

1
私にはうまくいきます。疑問に思っている方、オブジェクトを$connection.dispose()
破棄する

101

Invoke-Sqlcmdコマンドレットを使用できます

Invoke-Sqlcmd -Query "SELECT GETDATE() AS TimeOfQuery;" -ServerInstance "MyComputer\MyInstance"

http://technet.microsoft.com/en-us/library/cc281720.aspx


22
あなたがsqlサーバーのコンテキストにいる場合、誰かがこれは素晴らしいかもしれないと言及する必要がありますが、ワークステーションを使用している場合はそれほどではありません...
aikeru

10
これは、SQL Serverクライアントツール(SSMS)がインストールされている任意の場所で実行できます。SQL Serverを実行しているかどうかに関係なく、どのワークステーションからでも正常に機能します。
alroc 2013

3
コマンドレットを用意して、次のインポートを使用します Import-Module "sqlps" -DisableNameChecking
xx1xx

1
SQL 2008 R2をまだ使用している場合は、次の回避策
Vincent De Smet

2
Invoke-SqlCmdは、奇妙なエッジケースと一貫性のない動作の無限の悪夢です。列が出力される場合とそうでない場合があるのはなぜですか?エラーメッセージはどこにありますか?なぜ1台のコンピューターにあるのか、別のコンピューターにないのですか?どうすればインストールできますか?それぞれの質問への答えは最後の質問よりも悪いです。
Pxtl 2018

28

これが私がこのブログで見つけた例です。

$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


1
このソリューションは私にとってはうまくExecuteNonQuery()いきましたが、成功するとゼロを返しましたif ($cmd.ExecuteNonQuery() -ne 0)。私が使用する条件は次のとおりです。
Gixabel

影響を受けた行数を返すようです。docs.microsoft.com/en-us/dotnet/api/...
NicolasW

27

この関数は、クエリの結果を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
}

なぜこれがaを埋めるよりも望ましいのですかDataTableAdamの回答を参照)?
alroc 2013

2
大きな違いはないかもしれませんが、SqlDataReadersはリソースの消費量が少ないため、一般的に推奨されます。ここでは関係がないと思われますが、データのソースを気にせずにforeach句とwhere句で使用できるデータテーブルの代わりに、実際のオブジェクトを取得することをお勧めします。
mcobrien 2013

1
使用例はいいでしょう。
エリックシュナイダー、

十分な星がない場合があります
フレッドB

13

あなたにそれをしたい場合は、ローカルマシンの代わりに、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

ただ、中に埋める$サーバー名$データベース名および$クエリ変数と、あなたはどこへ行くか良いことがあります。

どうやって最初にこれを見つけたのかはわかりませんが、非常によく似たものがここにあります


12
Invoke-Sqlcmd -Query "sp_who" -ServerInstance . -QueryTimeout 3

powershellコマンドで使用されるSQLの接続数が表示されます
arnav


0

使用できるvarcharパラメータを使用したSQLインジェクションを回避するには


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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.