如何转义单引号或双引号的更新查询?

时间:2019-05-13 00:43:19

标签: sql-server powershell

我有一个查询来更新错误的状态字段

$error = "g is not a valid value for this element. An error occurred while parsing the 'SynchronizeSecurity' element at line 14, column 46 ('http://schemas.microsoft.com/analysisservices/2003/engine' namespace) under Envelope/Body/Execute/Command/Synchronize/SynchronizeSecurity."

Function Query($Query) {
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection 
$SqlConnection.ConnectionString = "Server=$Server;Initial Catalog=$Database;Integrated Security=SSPI" 
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand 
$SqlCmd.Connection = $SqlConnection 
$SqlCmd.CommandText = $Query 
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter 
$SqlAdapter.SelectCommand = $SqlCmd 
$DataSet = New-Object System.Data.DataSet 
$a=$SqlAdapter.Fill($DataSet)
$SqlConnection.Close() 
$DataSet.Tables[0] }

#Updating status field
Query "UPDATE [$Table]
SET [status] = '$error'
WHERE [db_name] = '$DB' AND [server] = '$server[-1])'"

此更新无效。我调试并发现它与单引号有关。如果我将错误内容直接粘贴到表中,则粘贴得很好。

我确保它不是代码问题,所以我将错误文本设置为“ Hi”和“ testing”,两次都用这些文本更新表就很好了。

所以现在我可以肯定的是,由于SET要求将字段文本用单引号引起来,并且我的错误包含单引号'SynchronizeSecurity',因此在某种程度上会发生冲突,因此不会使用错误消息。

我该如何规避?也许,反引号在此查询中如何工作?

1 个答案:

答案 0 :(得分:2)

您编写的内容存在一些问题:

  • 您已经编写了旨在从数据库中检索结果数据的代码,但是随后您调用了它并传递了一个更新查询-将二者分开;更新查询应使用ExecuteNonQuery运行,并且不需要数据适配器

  • 您尚未正确设置查询的参数,您只是使用字符串连接/内插来构建查询字符串,这充满了安全风险和意外后果,例如您在此处看到的引号问题

注释中有关交换单引号和双引号等的所有建议都被误导了,并且只是在伤口明显时的创可贴;使用参数,您可以插入任何喜欢的值变量内容。 https://bobby-tables.com提供了一些背景信息,说明了为什么它很重要以及c#的示例-非常接近PS。 https://powershellstation.com/2009/09/15/executing-sql-the-right-way-in-powershell/有一些相关的建议。我不使用powershell,所以我不会尝试将其包装在带有参数字典/的函数中(我可能会犯很多语法错误-在没有IDE的情况下将其写在手机上)循环中填充的数组参数,因此我将其留给读者练习。请查看2009年的博客文章以了解基本方法;)并在此记住此建议,因为您不需要sqladapter来运行更新查询等。因此,您可能需要放置两个函数(QuerySelect和QueryNonSelect),并在其中添加一些逻辑。 “如果sql字符串以SELECT开头的行,则调用QuerySelect,否则调用QueryNonSelect”,以便QueryNonSelect可以完成所有的更新/删除/合并/创建等操作

您的代码必须更像:

$SqlConnection = New-Object System.Data.SqlClient.SqlConnection 
$SqlConnection.ConnectionString = "Server=$Server;Initial Catalog=$Database;Integrated Security=SSPI" 
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand 
$SqlCmd.Connection = $SqlConnection 
$SqlCmd.CommandText = "update a set b=@c where d=@e"
$SqlCmd.Parameters.AddWithValue("@b", $error)
$SqlCmd.Parameters.AddWithValue("@e", $dbnameorwhatever)
$SqlCmd.ExecuteNonQuery()

最终指针:

  • 在您的sql字符串中使用@parameters。
  • 不能对列和表名进行@参数化(不能说“ update @tablename set @columnname = @ value1”-这里唯一有效的参数是@ value1。
  • 填充sqlcmd的Parameters集合。
  • 使用适当的方法运行查询-考虑将dataadapter用于返回行的任何内容。使用ExecuteNonQuery进行任何更改

    有一些避免使用AddWithValue(https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/)的理由,但这是在初次出发时使用的一种便捷方法,也是我在手机上向您编写代码的时候。考虑到该博客并根据需要更新您的编码