PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Clausola Go e IN in Postgres

Pre-compilazione della query SQL (prevenzione dell'iniezione SQL)

Se stai generando una stringa SQL con un segnaposto param per ciascuno dei valori, è più semplice generare subito l'SQL finale.

Nota che poiché i valori sono string s, c'è posto per l'attacco SQL injection, quindi prima testiamo se tutte le string i valori sono infatti numeri, e procediamo solo in tal caso:

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(")")

Eseguendo:

num := 0
if err := Db.QueryRow(buf.String()).Scan(&num); err != nil {
    log.Println(err)
}

Utilizzo di ANY

Puoi anche usare ANY di Postgresql , la cui sintassi è la seguente:

expression operator ANY (array expression)

Usando questo, la nostra query potrebbe assomigliare a questa:

SELECT COUNT(id) FROM tags WHERE id = ANY('{1,2,3}'::int[])

In questo caso puoi dichiarare la forma del testo dell'array come parametro:

SELECT COUNT(id) FROM tags WHERE id = ANY($1::int[])

Che può essere semplicemente costruito in questo modo:

tags := []string{"1", "2", "3"}
param := "{" + strings.Join(tags, ",") + "}"

Tieni presente che in questo caso non è richiesto alcun controllo poiché l'espressione dell'array non consentirà l'iniezione SQL (ma risulterà in un errore di esecuzione della query).

Quindi il codice completo:

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