Espaços reservados (
'?'
) só pode ser usado para inserir valores dinâmicos de escape para parâmetros de filtro (por exemplo, no WHERE
parte), onde os valores de dados devem aparecer, não para palavras-chave SQL, identificadores etc. Você não pode usá-lo para especificar dinamicamente o ORDER BY
OU GRUPAR POR
valores. Você ainda pode fazer isso, por exemplo, você pode usar
fmt.Sprintf()
para montar o texto da consulta dinâmica assim:ordCol := "title"
qtext := fmt.Sprintf("SELECT * FROM Apps ORDER BY %s DESC", ordCol)
rows, err := db.Query(qtext)
Itens a serem lembrados:
Ao fazer isso, você terá que defender manualmente contra injeção de SQL, por exemplo. se o valor do nome da coluna vier do usuário, você não pode aceitar nenhum valor e apenas inseri-lo diretamente na consulta, senão o usuário poderá fazer todo tipo de coisas ruins. Trivialmente você só deve aceitar letras do alfabeto inglês + dígitos + sublinhado (
'_'
). Sem tentar fornecer um verificador ou função de escape completo e abrangente, você pode usar este regexp simples que aceita apenas letras, dígitos e
'_'
em 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
}
Exemplos (experimente no 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