views:

2071

answers:

5

I am in the process of converting several queries which were hard-coded into the application and built on the fly to parameterized queries. I'm having trouble with one particular query, which has an in clause:

UPDATE TABLE_1 SET STATUS = 4 WHERE ID IN (1, 14, 145, 43);

The first parameter is easy, as it's just a normal parameter:

MySqlCommand m = new MySqlCommand("UPDATE TABLE_1 SET STATUS = ? WHERE ID IN (?);");
m.Parameters.Add(new MySqlParameter("", 2));

However, the second parameter is a list of integers representing the ids of the rows that need updating. How do I pass in a list of integers for a single parameter? Alternatively, how would you go about setting up this query so that you don't have to completely build it each and every time you call it, and can prevent SQL injection attacks?

A: 

You cannot use parameters for an IN clause.

Frederik Gheysels
A: 

i'd suggest creating a function (assuming that mysql supports user defined functions) to break the parameter apart to return a table.

MasterMax1313
A: 

Loop round your list of integers and perform individual updates.

MSSQL 2008 offers table-valued parameters to avoid this issue, I'm not aware of any similar functionality in MySQL.

Ian Nelson
That would be incredibly inefficient, considering that this query could, in some cases, have thousands of items in the IN clause.
Elie
Isn't there a limit to how many items you can have in an IN clause?
Svish
+3  A: 

You could build up the parametrised query "on the fly" based on the (presumably) variable number of parameters, and iterate over that to pass them in.

So, something like:

List foo; // assuming you have a List of items, in reality, it may be a List<int> or a List<myObject> with an id property, etc.

StringBuilder query = new StringBuilder( "UPDATE TABLE_1 SET STATUS = ? WHERE ID IN ( ?")
for( int i = 1; i++; i < foo.Count )
{   // Bit naive 
    query.Append( ", ?" );
}

query.Append( " );" );

MySqlCommand m = new MySqlCommand(query.ToString());
for( int i = 1; i++; i < foo.Count )
{
    m.Parameters.Add(new MySqlParameter(...));
}
Rowland Shaw
I was just thinking that. But would I gain the performance benefits of having a stored parameterized query if I did that?
Elie
Ado.Net suggests best performance is by creating a new connection, using it once and throwing it away -- at least for other SQL engines; After all, the query engine could optimise based on the query string to reuse them...
Rowland Shaw
+3  A: 

This is not possible in MySQL. You can create a required number of parameters and do UPDATE ... IN (?,?,?,?). This prevents injection attacks (but still requires you to rebuild the query for each parameter count).

Other way is to pass a comma-separated string and parse it.

Andrey Shchekin