Zástupné symboly ('?'
) lze použít pouze k vložení dynamických, uvozených hodnot pro parametry filtru (např. v WHERE
část), kde by se měly objevit hodnoty dat, nikoli pro klíčová slova SQL, identifikátory atd. Nelze jej použít k dynamickému zadání ORDER BY
NEBO GROUP BY
hodnoty.
Stále to však můžete udělat, například můžete použít fmt.Sprintf()
sestavit text dynamického dotazu takto:
ordCol := "title"
qtext := fmt.Sprintf("SELECT * FROM Apps ORDER BY %s DESC", ordCol)
rows, err := db.Query(qtext)
Na co je třeba pamatovat:
Pokud tak učiníte, budete se muset ručně bránit vs SQL injection, např. pokud hodnota názvu sloupce pochází od uživatele, nemůžete přijmout žádnou hodnotu a stačí ji vložit přímo do dotazu, jinak uživatel bude moci dělat různé špatné věci. Triviálně byste měli přijímat pouze písmena anglické abecedy + číslice + podtržítko ('_'
).
Aniž byste se pokoušeli poskytnout úplnou, rozsáhlou kontrolu nebo funkci escapování, můžete použít tento jednoduchý regulární výraz, který přijímá pouze anglická písmena, číslice a '_'
:
valid := regexp.MustCompile("^[A-Za-z0-9_]+$")
if !valid.MatchString(ordCol) {
// invalid column name, do not proceed in order to prevent SQL injection
}
Příklady (vyzkoušejte to na 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