如何将变量值注入到传递给" database.ExecuteWithResults()"

时间:2018-04-12 11:40:35

标签: sql-server powershell

使用powershell example from msdn docs作为参考,假设我正在与sql server数据库交谈:

$srv = new-Object Microsoft.SqlServer.Management.Smo.Server("(local)")
$db = New-Object Microsoft.SqlServer.Management.Smo.Database
$db = $srv.Databases.Item("AdventureWorks2012")
$db.ExecuteNonQuery("CHECKPOINT")
$ds = $db.ExecuteWithResults("SELECT * FROM Person.Address")
Foreach ($t in $ds.Tables)
{
   Foreach ($r in $t.Rows)
   {
      Foreach ($c in $t.Columns)
      {
          Write-Host $c.ColumnName "=" $r.Item($c)
      }
   }
}

如何将变量值注入传递给$db.ExecuteWithResults的sql中,就像我对sqlcmd一样,如下所示:

sqlcmd -v person="name" -i c:\testscript.sql

示例sql可能如下所示:

declare @PersonsName varchar(100) = '$(person)';

select * from Persons
where name = @PersonsName;

除了在sql本身上做一个令人讨厌的字符串替换之外,我在使用ExecuteWithResults时看不到包含此类注入的任何选项?

忽略这可能会在这里打开的任何sql注入问题,我不想围绕这个问题讨论安全问题。

1 个答案:

答案 0 :(得分:1)

Microsoft.SqlServer.Management.Smo.ExecuteWirthResults method documentation仅显示字符串和字符串集合重载,因此您将无法执行参数化查询。在PowerShell中,您只需在查询文本中指定变量名称,PS将在运行时替换为实际字符串:

$ds = $db.ExecuteWithResults("select * from Persons where name = '$person';")

考虑使用SqlClient而不是SMO来执行查询,以便您可以执行参数化查询:

$connectionString = "Data Source=.;Initial Catalog=AdventureWorks2012;Integrated Security=SSPI"
$connection = New-Object System.Data.SqlClient.SqlConnection($connectionString)
$command = New-Object System.Data.SqlClient.SqlCommand("CHECKPOINT", $connection)
$connection.Open()
[void]$command.ExecuteNonQuery()
$command.CommandText = "SELECT * FROM Person.Person WHERE LastName = @PersonsName;";
$person = "Duffy";
[void](($command.Parameters.Add("@PersonsName", [System.Data.SqlDbType]::NVarChar, 100)).Value = $person);
$dt = New-Object System.Data.DataTable
$da = New-Object System.Data.SqlClient.SqlDataAdapter($command)
[void]$da.Fill($dt)
$dt | Format-Table