Cataster
Cataster

Reputation: 3521

how to escape single or double quotes for update query?

I have a query to update status field with error

$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])'"

The update doesn't work. I debugged and found out that it has to do with single quotes. If I paste the error content directly in the table, it pastes in just fine.

I made sure that its not a code issue, so I set the error text to "Hi" and "testing" and both times it update the table with those texts just fine.

So now I am positive whats happening is that since the SET requires wrapping the field text in single quotes, and my error contains single quotes 'SynchronizeSecurity', its somehow conflicting and thus not updating the table with the error message.

How can I circumvent this? Maybe, how would a backtick work in this query?

Upvotes: 0

Views: 1257

Answers (1)

Caius Jard
Caius Jard

Reputation: 74605

There are a few problems with what you've written:

  • you've written code that is intended to retrieve result data from the database but then you've called it and passed in an update query - separate the two; update queries should be run using ExecuteNonQuery and do not require a dataadapter

  • you haven't properly parameterized your query, you've just used string concatenation/interpolation to build the query string and this is fraught with security risks and unintended consequences such as the quotes issue you see here

All the advice in the comments about swapping single and double quotes etc is misdirected, and is just a band aid on a gaping wound; use parameters and you can insert whatever value variable contents you like. https://bobby-tables.com has some background info on why it's important and examples for c# - very close to PS. https://powershellstation.com/2009/09/15/executing-sql-the-right-way-in-powershell/ Has some relevant advice. I don't do powershell so I'm not going to try and wrap this up in a function (I'll probably make a lot of syntax errors - writing this on a phone without the help of an IDE) with a parameters dictionary/array argument that is populated in a loop, so I'll leave that as an exercise for the reader. Check that 2009 blog article for the basic methodology ;) and remember this advice here that you don't need a sqladapter to run updating queries etc. You might hence want to put two functions (QuerySelect and QueryNonSelect) and put some logic in along the lines of "if sql string starts with SELECT call QuerySelect else call QueryNonSelect" so QueryNonSelect can do all your update/delete/merge/create etc

Your code needs to be more like:

$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()

Final pointers:

  • Use @parameters in your sql string.

  • Column and table names cannot be @parameterized (cannot say "update @tablename set @columnname = @value1" - the only valid parameter here is @value1.

  • Populate the sqlcmd's Parameters collection.

  • Run the query using the appropriate method - consider using a dataadapter for anything that returns rows. use ExecuteNonQuery for anything that makes changes

    There are reasons to avoid AddWithValue (https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/) but it's a useful convenience method when first setting out and also for me writing code to you on a cellphone.. consider that blog and update your coding as necessary

Upvotes: 2

Related Questions