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.
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:
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.