构建包装器以从 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
语句但是:
- 如果我执行
UPDATE
或 INSERT
,我想 return 受影响的行数,或者一个错误(如果适用)
- 应忽略任何其他查询(
ALTER
、DROP
、DELETE
),错误消息 returned
最好的方法是:
- 识别查询命令的排序(
SELECT
,DROP
)?
- 在一个函数中处理所有请求? (switch 语句或重定向到特定函数?)
非常感谢任何帮助。
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()
}
}
}
}
我正在尝试构建一个通用包装器,以便从 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
语句但是:
- 如果我执行
UPDATE
或INSERT
,我想 return 受影响的行数,或者一个错误(如果适用) - 应忽略任何其他查询(
ALTER
、DROP
、DELETE
),错误消息 returned
最好的方法是:
- 识别查询命令的排序(
SELECT
,DROP
)? - 在一个函数中处理所有请求? (switch 语句或重定向到特定函数?)
非常感谢任何帮助。
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()
}
}
}
}