Vorbereitung der SQL-Abfrage (Verhinderung der SQL-Einschleusung)
Wenn Sie eine SQL-Zeichenfolge mit einem param-Platzhalter für jeden der Werte generieren, ist es einfacher, gleich die endgültige SQL zu generieren.
Beachten Sie, dass Werte string
sind s gibt es Platz für SQL-Injection-Angriffe, also testen wir zuerst, ob der gesamte string
Werte sind in der Tat Zahlen, und wir fahren nur fort, wenn dies der Fall ist:
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(")")
Ausführen:
num := 0
if err := Db.QueryRow(buf.String()).Scan(&num); err != nil {
log.Println(err)
}
Mit ANY
Sie können auch ANY
von Postgresql verwenden , dessen Syntax wie folgt lautet:
expression operator ANY (array expression)
Damit könnte unsere Abfrage wie folgt aussehen:
SELECT COUNT(id) FROM tags WHERE id = ANY('{1,2,3}'::int[])
In diesem Fall können Sie die Textform des Arrays als Parameter angeben:
SELECT COUNT(id) FROM tags WHERE id = ANY($1::int[])
Was einfach so aufgebaut werden kann:
tags := []string{"1", "2", "3"}
param := "{" + strings.Join(tags, ",") + "}"
Beachten Sie, dass in diesem Fall keine Überprüfung erforderlich ist, da der Array-Ausdruck keine SQL-Injection zulässt (sondern zu einem Abfrageausführungsfehler führt).
Also der vollständige Code:
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)
}