es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo parametrizar una consulta dinámica en Go

Los usuarios pueden solicitar precios de productos basados en varios criterios diferentes, lo que potencialmente dará lugar a acceder a diferentes columnas en una tabla. Estoy recorriendo los productos solicitados y construyendo un conjunto de consultas, pero estoy teniendo algunos problemas.

Ejecutarlos uno por uno y combinar los resultados lleva mucho más tiempo que hacer una unión. Así que intenté construir la consulta de la siguiente manera, que funciona y es rápido, pero ahora es susceptible a inserciones.

¿Hay una mejor manera de hacer esto sin la unión? ¿O hay una forma sencilla de parametrizar una consulta dinámica como esta?

    var fullQuery string
    var counter int
    for i, d:= range dataMap{
    if counter != 0 {
        fullQuery = fullQuery + " UNION "
    }
    var records string
    for _, p := range d{
        records = records + `'` + string(p) + `',`
    }
    recordLength:= len(records)
    if recordLength> 0 && records [recordLength-1] == ',' {
        records = records[:recordLength-1]
    }
    counter++
    fullQuery = fullQuery + fmt.Sprintf(`
SELECT 
    price_`+fmt.Sprint(p.type)+` as price,                
  FROM products
  WHERE products.id in (%s) and products.store= %s

`, records, p.store)

}

err := sqlx.Select(db, &dataStruct, fullQuery)

Entonces, en algunas situaciones, puedo tener la siguiente consulta:

SELECT 
    price_`+fmt.Sprint(p.type)+` as price,
  FROM products
  WHERE products.id in (%s) and products.store= %s

Y en otros casos (dependiendo de la solicitud), puedo tener algo como esto:

SELECT 
    price_`+fmt.Sprint(p.type)+` as price,
  FROM products
  WHERE products.id in ('testid1', 'testid2') and products.store= 2
UNION
SELECT 
    price_`+fmt.Sprint(p.type)+` as price,
  FROM products
  WHERE products.id in ('testid3', 'testid4') and products.store= 1

Si supiera con seguridad cuál es la consulta, simplemente usaría $1, $2, etc., pero no creo que pueda hacerlo aquí porque no sé cuántos parámetros habrá y todos deben ser diferentes.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Una forma de evitar el uso de UNION en consultas generadas dinámicamente es utilizar una declaración CASE. Esto permite tener diferentes condiciones y declaraciones SELECT en función de los criterios solicitados por el usuario. Aquí tienes un ejemplo de consulta:

        CASE 
            WHEN products.id IN ('testid1', 'testid2') AND products.store = 2 
                THEN price_type1 
            WHEN products.id IN ('testid3', 'testid4') AND products.store = 1 
                THEN price_type2 
            ELSE NULL 
        END AS price 
    FROM products 
    WHERE products.id IN ('testid1', 'testid2', 'testid3', 'testid4') 
        AND products.store IN (1, 2)
    

    En esta consulta, estamos utilizando una declaración CASE para seleccionar condicionalmente la columna de precio correcta en función del producto y la tienda solicitados. Todavía podemos incluir todos los productos solicitados en una sola consulta.

    Para parametrizar esta consulta, puedes utilizar el mismo número de parámetros cada vez y repetirlos según sea necesario. Por ejemplo, si tienes un máximo de 10 productos y tiendas, puedes utilizar $1-$20 en tu consulta y pasar los valores relevantes en consecuencia.

    Otra opción es utilizar un procedimiento almacenado para generar la consulta dinámica y pasar los parámetros necesarios. Esto puede ayudar a evitar la inyección de SQL ya que las entradas de usuario no se utilizan directamente en la consulta.

    Es importante sanitizar las entradas de usuario y validar los criterios solicitados antes de construir la consulta para evitar cualquier consecuencia no deseada.

Comments are closed.