Tengo esta pregunta acerca de la MySqlParameter de el .NET conector.

Tengo esta consulta:

SELECT * FROM table WHERE id IN (@parameter)

Y la MySqlParameter es:

intArray = new List<int>(){1,2,3,4};

...connection.Command.Parameters.AddWithValue("parameter", intArray);

Esto es posible?
Es posible pasar un array de int a un solo MySqlParameter?
La otra solución será convertir el array de int para una cadena como «1,2,3,4», pero este, cuando me pase a la MySqlParameter y esto es reconocido como una cadena, se pone en la consulta sql como «1\,2\,3\,4» y esto no devuelven los valores esperados.

@ ACTUALIZACIÓN: Parece que el mysql connector equipo debe trabajar un poco más duro.

  • No sólo de MySQL. Hasta donde yo sé, esto no es apoyado en MSSQL, ni es parte de la T-SQL especificación.
  • NHibernate y otros Orm dar la impresión de apoyar esto, pero bajo el capó que están haciendo la concatenación de cadenas (con o sin parámetros)
InformationsquelleAutor Phoenix_uy | 2011-04-15

8 Comentarios

  1. 15

    cuando me pase a la MySqlParameter y esto es reconocido como una cadena, se pone en la consulta sql como «1\,2\,3\,4» y esto no devuelven los valores esperados.

    Me encontré con esta última noche. He encontrado que FIND_IN_SET funciona aquí:

    SELECT * FROM table WHERE FIND_IN_SET(id, @parameter) != 0
    ...
    intArray = new List<int>(){1,2,3,4};
    conn.Command.Parameters.AddWithValue("parameter", string.Join(",", intArray));

    Al parecer esto tiene algunas limitaciones de longitud (he encontrado tu post buscando una solución alternativa), pero esto puede funcionar para usted.

    • Siempre y cuando no te importa no el uso de índices. O correr el riesgo de un ataque de inyección. Mientras que en este ejemplo concreto de que estés bien porque va de List<int> así que usted está garantizada sin la inyección de SQL, si la lista contiene cadenas, usted necesita para asegurarse de que son desinfectados en primer lugar.
    • El comentario anterior es engañoso… el Barro es mediante una consulta parametrizada para lograr el objetivo. Consultas con parámetros son, literalmente, lo que se utiliza para evitar la inyección de sql en las cadenas sin tener que fregar manualmente el contenido de la cadena. Este es un gran ejemplo de logro de la meta.
  2. 5

    Parámetros no funcionan con EN. Siempre he incrustado cosas tales como una cadena en la misma consulta. Mientras que generalmente se considera de mala forma porque la inyección de SQL, si usted está construyendo la consulta de un establecimiento inflexible de tipos numéricos lista, entonces no debe haber ninguna posibilidad de cualquier entrada externa que se dañe en una manera significativa.

    • Quizas me he explicado mal.. cuando me dijo: «convertir la matriz de la cadena y que pase» no me refiero a «SELECT * FROM tabla where id IN(» + cadenas + «)»…
    • Yo sé, y estoy diciendo que no es posible hacerlo de la manera que usted desea.
  3. 3

    usted va a tener que iterar a través de su matriz y crear la lista de

    //no parameters
    var sb = new StringBuilder();
    for(int i=0;i<intArray.Length;i++)
    {
        sb.Append(intArray[i] + ",");//no SQL injection they are numbers
    }
    if (sb.Length>0) {sb.Length-=1;}
    string sql = "SELECT * FROM table WHERE id IN (" + sb.ToString() + ")";

    ACTUALIZACIÓN: después de Haber pensado más en este voy a volver a mi respuesta original (abajo) que es el uso de los parámetros. Optimizaciones de construido consultas y cualquiera que sea el motor de base de datos puede reunir a usted.

    //no parameters
    var sb = new StringBuilder();
    for(int i=0;i<intArray.Length;i++)
    {
        sb.AppendFormat("p{0},", i);//no SQL injection they are numbers
        connection.Command.Parameters.AddWithValue("p"+i, intArray[i]);
    }
    if (sb.Length>0) {sb.Length-=1;}
    string sql = "SELECT * FROM table WHERE id IN (" + sb.ToString() + ")";
    • que todo el bucle y el cheque puede ser reemplazado con string.Join(",", intArray)
    • bueno, sí, si quería corta un código legible 🙂 en lugar de en mi caso olvidado acerca de ese método
    • los olores de la inyección de sql. Incluso si usted está usando un relativamente «seguros» escriba como un int de la secuencia, la omi es un mal hábito.
    • Yo no estaba abajo del votante por cierto -, mientras que más de la necesaria esta es todavía una respuesta que se aplica a la cuestión
    • Coehoorn, mal hábito sí, sin embargo, si usted está haciendo un diseño activo de la decisión, entonces es una solución sólida (si es que se requiere como se ha señalado)
    • «los olores de la inyección sql» estoy de acuerdo, y no me gusta esto, pero también es la única manera de resolver el problema en algunas situaciones sin hacer algo tonto como la iteración «[email protected]_x..» una y otra vez. No hay absolutamente ningún riesgo cuando se utiliza establecimiento inflexible de tipos de datos numéricos. La clave para evitar problemas como la inyección sql no es sólo una fe ciega en hacer las cosas de una cierta manera – es también saber lo que están haciendo.
    • La cosa que como ya he dicho… actualmente estoy usando el string s = string.Join(«,», intArray), pero cuando me pase de comandos.Parámetro.AddWithValue(«parámetro», s) en la consulta, mysql conector de pasar el parámetro como «1\,2\,3» y la consulta select no funciona como se esperaba.
    • una cadena que contiene una lista delimitada por comas de los números no puede ser el valor de un parámetro en cualquier controlador SQL sé. Nota: en mi ejemplo estoy configuración de la valor SQL, no hay parámetros. Como ya se mencionó que no se puede pasar y de la matriz con el SQL. Voy a actualizar mi respuesta con más detalle

  4. 2

    Usted tiene un par de opciones, aquí (en orden de preferencia):

    1. El uso de una base de datos que soporta los parámetros con valores de tabla. Este es el sólo manera de conseguir la sintaxis exacta que usted desea.
    2. Los datos tiene que venir de alguna parte: su base de datos, usuario de la acción, o la generada por el equipo de origen.

      • Si los datos ya están en la base de datos, utilizar una subconsulta en lugar.
      • Para otra máquina que genera los datos, el uso de BULK INSERT, SqlBulkCopy, o su base de datos preferida de la importación masiva de herramientas.
      • Si es creado por el usuario, agregar a una tabla separada en cada acción del usuario y, a continuación, utilizar una sub consulta.

        Un ejemplo de esto es un carrito de la compra. Un usuario puede seleccionar varios elementos a la compra. En lugar de mantener estos en la aplicación y la necesidad de agregar todos los elementos a una orden de una sola vez al hacer el check out, añadir cada elemento de una tabla de la base de datos como el usuario selecciona o cambia.

    3. Tener un sql función definida por el usuario que se desempaqueta un parámetro de cadena en una tabla y devuelve la tabla como un conjunto se puede utilizar con un() DE la expresión. Ver el artículo enlazado más abajo para obtener más información detallada sobre cómo funciona esto.
    4. Construir una cadena de lista o lista de parámetros de forma dinámica en el cliente (como se muestra en otras respuestas). Tenga en cuenta que este es mi menos opción preferida.

    La definitiva (y me refiero a definitiva) trabajos sobre el tema está aquí:

    http://www.sommarskog.se/arrays-in-sql.html

    El artículo largo, pero en una buena forma. El autor es un experto del sql server, pero los conceptos que sobre todo se aplican a MySQL así.

  5. 1

    Como sé que usted no puede proporcionar cualquier matriz como parámetro declaración preparada. EN() no admite parámetros como una matriz.

    • Usted puede hacer la cosa… ¿el «where id IN (1,2,3,4)» es el mismo de «where id = 1 id = 2 o id = 3 o id = 4», al menos esto funciona para mí 🙂
    • COMO puedo ver en su ejemplo, no hay parámetros para enlazar. Y hablamos de ellos solamente.
  6. 0

    Creo que no hay una manera que usted puede agregar les gusta eso, pero tal vez usted podría recorrer la lista y generar la consulta de forma dinámica.

    Por ejemplo:

    var intArray = new List<int>(){1,2,3,4};
    if (intArray.Count > 0) {
        var query = "SELECT * FROM table WHERE id IN (";
        for (int i = 0; i < intArray.Count; i++) {
            //Append the parameter to the query
            //Note: I'm not sure if mysql uses "@" but you can replace this if needed
            query += "@num" + i + ",";
            //Add the value to the parameters collection
            ...connection.Command.Parameters.AddWithValue("num" + i, intArray[i]);
        }
        //Remove the last comma and add the closing bracket
        query = query.Substring(0, query.Length - 1) + ");";
        //Execute the query here
    }

    De esta manera, usted puede incluso utilizar una forma diferente escribió lista y todavía cosechar los beneficios de consultas parametrizadas. Sin embargo, no sé si habría problemas de rendimiento con grandes listas, pero sospecho que sería el caso.

    • ¿Por qué el downvote?
  7. 0

    Esto no funciona bien para grandes listas, pero es la sólo cosa que he encontrado que funciona si han para pasar una lista como un parámetro.

    Lugar de

    SELECT * FROM table WHERE id IN (@parameter)

    Tienes que hacer esto:

    SELECT *
    FROM table
    WHERE INSTR(','+@parameter+',', ','+CAST(the_column AS CHAR) + ',')

    A continuación, puede pasar en su lista con string.Join(",", intArray)

    Es un parche, pero funciona.

  8. 0

    Respuesta de Barro sólo funciona para la primera int en la lista de parámetros. Esto significa ‘2,1,3,4’ no funcionará si el id es 1, por ejemplo.

    Ver FIND_IN_SET() vs()DE .

    No hay comentario posible por ahora, pero también véase la respuesta de Matt Elena.
    Iba a editar su respuesta, pero no puede. INSTR no parece funcionar en un caso DONDE con más de un id (devuelve únicamente en el resultado).

    Pero sustitución de INSTR con LOCATE hacer su solución de trabajo (con String.Join(",", intArray) como parámetro agregado) … HASTA el VOTO de mí:

    LOCATE(CONCAT(',' , CAST(id AS CHAR) , ',') , CONCAT(',' , CAST(@paramter AS CHAR) , ',')) <> 0

Dejar respuesta

Please enter your comment!
Please enter your name here