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에서 폐기가 중요하지 않습니까?
Maslow

2
@Maslow 확실히 말할 수 없었습니다. 이것은 객체를 폐기하지 않고 잘 작동한다는 것을 알고 있지만 단일 powershell.exe 프로세스가 있으면 닫지 않고 몇 주에 걸쳐 이것을 여러 번 호출하면 결국 문제가 될 수 있습니다. 그것을 테스트해야 할 것입니다.
Chris Magnuson 14

1
이렇게하면 사용자 입력에 의존하는 소스에서 쿼리 데이터를 읽는 데 의존하는 경우 SQL 주입 공격에 취약한 스크립트를 작성해야합니다.
Joel Coehoorn

4
@AllTradesJack Google Sql Injection. Invoke-Sql 명령에는 명령 텍스트와 별도로 매개 변수를 포함시킬 수있는 방법이 없습니다. 이것은 문자열 연결을 사용하여 쿼리를 작성하는 것을 거의 보장합니다.
Joel Coehoorn

1
나를 위해 잘 작동합니다. 궁금한 $connection.dispose()점이 있으시면 , 물건을 처분하고 그냥 추가하십시오 . 비록 그것이 차이가
있는지는 모르겠습니다

101

Invoke-Sqlcmdcmdlet을 사용할 수 있습니다

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

3
다음 가져 오기를 사용하여 cmdlet을 사용할 수 있습니다. Import-Module "sqlps" -DisableNameChecking
xx1xx

1
당신은 SQL 2008 R2에 아직도 경우에 당신은 모듈 주위에 일을 사용할 필요가 : sev17.com/2010/07/10/making-a-sqlps-module
빈센트 드 스멧

2
Invoke-SqlCmd는 기괴한 엣지 케이스와 일관되지 않은 동작으로 끝없는 악몽입니다. 때때로 다른 시간이 아닌 열을 출력하는 이유는 무엇입니까? 내 오류 메시지는 어디에 있습니까? 다른 컴퓨터가 아닌 다른 컴퓨터에있는 이유는 무엇입니까? 어떻게 설치합니까? 각 질문에 대한 대답은 마지막 질문보다 나쁩니다.
Pxtl

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()성공하면 0을 반환했습니다 if ($cmd.ExecuteNonQuery() -ne 0). 사용 조건은 다음과 같습니다 .
Gixabel

영향을받은 줄 수를 반환하는 것 같습니다. docs.microsoft.com/ko-kr/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
}

이것을 채우는 것보다 왜 이것이 바람직한 가요 DataTable( Adam 's answer 참조 )?
alroc 2012 년

2
큰 차이는 없지만 SqlDataReader는 일반적으로 적은 리소스를 사용하기 때문에 선호됩니다. 그것은 관련이 없을 것 같지만 데이터 소스에 대해 걱정하지 않고 foreach 및 where 절에서 사용할 수있는 데이터 테이블 대신 실제 객체를 다시 가져 오는 것이 좋습니다.
mcobrien

1
예제 사용법이 좋을 것입니다.
에릭 슈나이더

때때로 별이 충분하지 않습니다
Fred 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

$ ServerName , $ DatabaseName$ Query 변수를 입력하기 만하면 됩니다.

우리가 처음에 이것을 어떻게 찾았는지 잘 모르겠지만 여기에 매우 비슷한 것이 있습니다 .


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.