Marcadores de posición ('?'
) solo se puede usar para insertar valores de escape dinámicos para parámetros de filtro (por ejemplo, en WHERE
parte), donde deben aparecer los valores de datos, no para palabras clave de SQL, identificadores, etc. No puede usarlo para especificar dinámicamente el ORDER BY
O GROUP BY
valores.
Sin embargo, aún puede hacerlo, por ejemplo, puede usar fmt.Sprintf()
para ensamblar el texto de consulta dinámica de esta manera:
ordCol := "title"
qtext := fmt.Sprintf("SELECT * FROM Apps ORDER BY %s DESC", ordCol)
rows, err := db.Query(qtext)
Cosas a tener en cuenta:
Al hacerlo, tendrá que defenderse manualmente frente a la inyección de SQL, p. si el valor del nombre de la columna proviene del usuario, no puede aceptar ningún valor y simplemente insertarlo directamente en la consulta; de lo contrario, el usuario podrá hacer todo tipo de cosas malas. Trivialmente, solo debe aceptar letras del alfabeto inglés + dígitos + guión bajo ('_'
).
Sin intentar proporcionar una función de verificación o escape completa y completa, puede usar esta expresión regular simple que solo acepta letras, dígitos y '_'
en inglés :
valid := regexp.MustCompile("^[A-Za-z0-9_]+$")
if !valid.MatchString(ordCol) {
// invalid column name, do not proceed in order to prevent SQL injection
}
Ejemplos (pruébelo en Go Playground ):
fmt.Println(valid.MatchString("title")) // true
fmt.Println(valid.MatchString("another_col_2")) // true
fmt.Println(valid.MatchString("it's a trap!")) // false
fmt.Println(valid.MatchString("(trap)")) // false
fmt.Println(valid.MatchString("also*trap")) // false