Forudbygning af SQL-forespørgslen (forhindring af SQL-injektion)
Hvis du genererer en SQL-streng med en param-pladsholder for hver af værdierne, er det nemmere blot at generere den endelige SQL med det samme.
Bemærk, at da værdier er string
s, der er plads til SQL-injektionsangreb, så vi tester først, om alle string
værdier er faktisk tal, og vi fortsætter kun, hvis det er tilfældet:
tags := []string{"1", "2", "3"}
buf := bytes.NewBufferString("SELECT COUNT(id) FROM tags WHERE id IN(")
for i, v := range tags {
if i > 0 {
buf.WriteString(",")
}
if _, err := strconv.Atoi(v); err != nil {
panic("Not number!")
}
buf.WriteString(v)
}
buf.WriteString(")")
Udfører det:
num := 0
if err := Db.QueryRow(buf.String()).Scan(&num); err != nil {
log.Println(err)
}
Brug af ANY
Du kan også bruge Postgresqls ANY
, hvis syntaks er som følger:
expression operator ANY (array expression)
Ved at bruge det kan vores forespørgsel se sådan ud:
SELECT COUNT(id) FROM tags WHERE id = ANY('{1,2,3}'::int[])
I dette tilfælde kan du erklære arrayets tekstform som en parameter:
SELECT COUNT(id) FROM tags WHERE id = ANY($1::int[])
Som ganske enkelt kan bygges sådan her:
tags := []string{"1", "2", "3"}
param := "{" + strings.Join(tags, ",") + "}"
Bemærk, at der ikke kræves kontrol i dette tilfælde, da array-udtrykket ikke tillader SQL-injektion (men vil snarere resultere i en forespørgselsudførelsesfejl).
Så den fulde kode:
tags := []string{"1", "2", "3"}
q := "SELECT COUNT(id) FROM tags WHERE id = ANY($1::int[])"
param := "{" + strings.Join(tags, ",") + "}"
num := 0
if err := Db.QueryRow(q, param).Scan(&num); err != nil {
log.Println(err)
}