2009-03-16 30 views
6

Estoy en el proceso de convertir varias consultas que fueron codificadas en la aplicación y construidas sobre la marcha para consultas parametrizadas. Tengo problemas con una consulta en particular, que tiene una in cláusula:C# Parameterized Query MySQL con la cláusula `in`

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

El primer parámetro es fácil, ya que es sólo un parámetro normales:

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

Sin embargo, el segundo parámetro es una lista de enteros que representan los identificadores de las filas que necesitan actualización. ¿Cómo paso una lista de enteros para un solo parámetro? De forma alternativa, ¿cómo haría para configurar esta consulta para que no tenga que compilarla por completo cada vez que la llame y pueda evitar los ataques de inyección SQL?

+0

duplicados de http://stackoverflow.com/questions/337704/parameterizing-a-sql-in-clause (aunque eso es servidor SQL en lugar de MySQL ; sin embargo, es poco probable que sea realmente diferente) –

+0

Se reconoció que la solución ofrecida allí era increíblemente lenta, aunque responde la segunda mitad de mi pregunta. – Elie

+0

Hay * muchas * soluciones ofrecidas allí. La respuesta aceptada no es la más popular. –

Respuesta

4

Se podría construir la consulta definido en los parámetros "sobre la marcha", basada en la (presumiblemente) número variable de parámetros, y pasar sobre ese pasarlos en

Por lo tanto, algo así como:.

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

Estaba pensando eso. Pero, ¿obtendría los beneficios de rendimiento de tener una consulta parametrizada almacenada si lo hiciera? – Elie

+0

Ado.Net sugiere que el mejor rendimiento es crear una nueva conexión, usarla una vez y tirarla, al menos para otros motores SQL; Después de todo, el motor de consulta podría optimizar en función de la cadena de consulta para reutilizarlos ... –

2

No puede usar parámetros para una cláusula IN.

-1

sugiero crear una función (suponiendo que mysql admite funciones definidas por el usuario) para separar el parámetro y devolver una tabla.

0

Haz un círculo alrededor de tu lista de enteros y realiza actualizaciones individuales.

MSSQL 2008 ofrece parámetros con valores de tabla para evitar este problema, no conozco ninguna funcionalidad similar en MySQL.

+0

Eso sería increíblemente ineficiente, considerando que esta consulta podría, en algunos casos, tener miles de elementos en la cláusula IN. – Elie

+0

¿No hay un límite en la cantidad de elementos que puede tener en una cláusula IN? – Svish

5

Esto no es posible en MySQL. Puede crear un número requerido de parámetros y ACTUALIZAR ... EN (?,?,?,?). Esto evita los ataques de inyección (pero aún así requiere que reconstruya la consulta para cada recuento de parámetros).

Otra forma es pasar una secuencia separada por comas y analizarla.

1

vieja pregunta, pero en caso de que alguien viene a través de esta vía Google, esto es lo que utilizo:

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; 

Nota: FIND_IN_SET es una función específica de MySQL.

crédito a quien crédito merece: Ver esta pregunta: Add List<int> to a mysql parameter

Cuestiones relacionadas