PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Go- und IN-Klausel in Postgres

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)
}