2009-03-16 3 views
6

Я в процессе преобразования нескольких запросов, которые были жестко закодированы в приложении и построены на лету для параметризованных запросов. У меня возникли проблемы с одним конкретным запросом, который имеет in положение:C# Параметрированный запрос MySQL с условием `in`

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

Первый параметр легко, так как это просто нормальный параметр:

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

Однако, второй параметр является список целых чисел, представляющих идентификаторы строк, которые нуждаются в обновлении. Как передать список целых чисел для одного параметра? В качестве альтернативы, как бы вы решили настроить этот запрос, чтобы вам не приходилось полностью его создавать каждый раз, когда вы его вызываете, и можете предотвратить атаки SQL-инъекций?

+0

дубликата http://stackoverflow.com/questions/337704/parameterizing-a-sql-in-clause (хотя это SQL-сервер вместо MySQL , вряд ли будет действительно отличаться) –

+0

Решение, предлагаемое там, было признано невероятно медленным, хотя оно отвечает на вторую половину моего вопроса. – Elie

+0

Есть * лоты * предлагаемых решений. Принятый ответ не самый популярный. –

ответ

4

Вы можете застроить параметрический запрос «на лету» на основе (предположительно) переменного числе параметров, и перебирать, что передать их в

Так, что-то вроде:.

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(...)); 
} 
+0

Я так думал. Но могу ли я получить преимущества производительности при сохранении параметризованного запроса, если бы я это сделал? – Elie

+0

Ado.Net предлагает лучшую производительность, создавая новое соединение, используя его один раз и отбрасывая - по крайней мере, для других SQL-движков; В конце концов, механизм запросов может оптимизировать на основе строки запроса, чтобы повторно использовать их ... –

2

Вы не можете использовать параметры для предложения IN.

-1

Я бы предложил создать функцию (предполагая, что mysql поддерживает определенные пользователем функции), чтобы разбить параметр отдельно, чтобы вернуть таблицу.

0

Прокрутите список целых чисел и выполните отдельные обновления.

MSSQL 2008 предлагает табличные параметры, чтобы избежать этой проблемы, я не знаю о какой-либо аналогичной функциональности в MySQL.

+0

Это было бы невероятно неэффективно, учитывая, что в некоторых случаях этот запрос может иметь тысячи элементов в предложении IN. – Elie

+0

Разве нет предела тому, сколько предметов вы можете иметь в разделе IN? – Svish

5

Это невозможно в MySQL. Вы можете создать необходимое количество параметров и выполнить UPDATE ... IN (?,?,?,?). Это предотвращает атаки на инъекции (но все же требует от вас перестроить запрос для каждого параметра).

Другой способ - передать строку, разделенную запятой, и проанализировать ее.

1

Старый вопрос, но в случае, если кто-то приходит через это с помощью Google, вот что я использую:

int status = 4; 
string ids = "1,14,145,43";  

m.Parameters.AddWithValue("@Status", status); 
m.Parameters.AddWithValue("@IDs", ids); 

UPDATE TABLE_1 SET STATUS = @Status WHERE FIND_IN_SET(ID, @IDs) > 0; 

Примечание: FIND_IN_SET является специфической функцией MySql.

кредит, где кредит должен: Смотрите этот вопрос: Add List<int> to a mysql parameter