构建包装器以从 Powershell 执行 SQL 查询

Building a wrapper to perform SQL queries from Powershell

我正在尝试构建一个通用包装器,以便从 Powershell 中轻松查询 SQL 服务器数据库并处理结果:

$result = SQL("SELECT * CustomerID FROM [dbo].[TblCustomers]")

$result.Tables[0] | Foreach {
    Write-Host $_.CustomerID
}

包装器

## Wrapper for SQL Select statements
#
Function SQL {
    param(
        [string]$query
    )

    $Server = "SQLEXPRESS"
    $DBase  = "DataStore"
    $User   = "DataUser"
    $Pass   = "DataPass"

    $conn  = New-Object System.Data.SqlClient.SqlConnection("Server=$Server;Database=$DBase;User=$User;Password=$Pass;Connect Timeout=15")

    try {
        $conn.Open()
        $cmd     = New-Object System.Data.SqlClient.SqlCommand($query,$conn)
        $adapter = New-Object System.Data.SqlClient.SqlDataAdapter($cmd)
        $dataset = New-Object System.Data.DataSet
        $adapter.Fill($dataset) | Out-Null
        $conn.Close()
    }
    catch {
        $ex = $_.Exception
        Write-Error "$ex.Message"
        continue
    }

    return $dataset
}

这仅适用于 SELECT 语句但是:

最好的方法是:

非常感谢任何帮助。

P.S。因为我是唯一一个在后端脚本中使用该函数的人,所以我不太担心 SQL 注入。

[编辑]

我现在有:

Function Query {
    param (
        [string]$query
        [string]$server
        [string]$dbase
        [string]$user
        [string]$pass
    )

    if ($user) { 
        $connstr = "Server={0};Database={1};User ID={2};Password={3};Trusted_Connection=False;Connect Timeout=15" -f $server, $dbase, $user, $pass 
    } 
    else { 
        $connstr = "Server={0};Database={1};Integrated Security=True;Connect Timeout=15" -f $server, $dbase
    }
    $conn.ConnectionString = $connstr 


    switch ($query.Split()[0]) {
        "SELECT" {
            $cmd = New-Object System.Data.SqlClient.SqlCommand($query,$conn)
            $adapter = New-Object System.Data.SqlClient.SqlDataAdapter($cmd)
            $dataset = New-Object System.Data.DataSet
            $adapter.Fill($dataset) | Out-Null
            return $dataset
        }
        "UPDATE" {
            $cmd = New-Object System.Data.SqlClient.SqlCommand($query,$conn)
            return $cmd.ExecuteNonQuery()
        }
        "INSERT" {
            $cmd = New-Object System.Data.SqlClient.SqlCommand($query,$conn)
            return $cmd.ExecuteNonQuery()
        }
    }
}

这是您可以构建的示例,它使用参数集来识别查询类型。 executenonquery 方法returns 查询影响的行数。我使用 validatescript 属性来防止任何包含单词 drop、delete 或 alter 的查询。您可以根据需要添加其他人。我没有方便测试的 SQL 框,但这应该可以。您还可以调整它以使用服务器、数据库、用户、密码的参数,而不是对它们进行硬编码以使其可重用。

function Invoke-SQLQuery
{
    [CmdletBinding(DefaultParameterSetName='SELECT', 
                  SupportsShouldProcess=$true, 
                  ConfirmImpact='Medium')]
    Param
    (
        # Param1 help description
        [Parameter(Mandatory=$true, 
                   Position=0,
                   ParameterSetName='SELECT')]
        [Parameter(Mandatory=$true, 
                   Position=0,
                   ParameterSetName='UPDATE')]
        [Parameter(Mandatory=$true, 
                   Position=0,
                   ParameterSetName='INSERT')]
        [ValidateNotNull()]
        [ValidateNotNullOrEmpty()]
        [ValidateScript({$_ -notmatch "ALTER|DROP|DELETE" })]
        $Query,

        # Param2 help description
        [Parameter(ParameterSetName='SELECT')]
        [switch]
        $Select,

        # Param3 help description
        [Parameter(ParameterSetName='UPDATE')]
        [switch]
        $Update,

        [Parameter(ParameterSetName='INSERT')]
        [switch]
        $Insert
    )

    Begin
    {
        $Server = "SQLEXPRESS"
        $DBase  = "DataStore"
        $User   = "DataUser"
        $Pass   = "DataPass"
        $conn  = New-Object System.Data.SqlClient.SqlConnection("Server=$Server;Database=$DBase;User=$User;Password=$Pass;Connect Timeout=15")
    }
    Process
    {
        if ($pscmdlet.ShouldProcess("$Server", "Execute Query"))
        {
            try
            {
                $conn.Open()
                switch($pscmdlet.ParameterSetName){
                    "SELECT" {
                                $cmd = New-Object System.Data.SqlClient.SqlCommand($query,$conn)
                                $adapter = New-Object System.Data.SqlClient.SqlDataAdapter($cmd)
                                $dataset = New-Object System.Data.DataSet
                                $adapter.Fill($dataset) | Out-Null
                                return $dataset
                        }
                    "UPDATE" {
                            $cmd = New-Object System.Data.SqlClient.SqlCommand($query,$conn)
                            return $cmd.ExecuteNonQuery()
                        }
                    "INSERT" {
                            $cmd = New-Object System.Data.SqlClient.SqlCommand($query,$conn)
                            return $cmd.ExecuteNonQuery()
                        }
                    }
                }
               catch [System.Data.SqlClient.SqlException]
               {
                    #Implement Error Handling
                    $ex = $_.Exception
                    Write-Error "$ex.Message"
                    continue
               }
               finally
               {
                   $conn.Close()
                   $conn.Dispose()
               }
           }
      }
}