web-dev-qa-db-fra.com

Comment exécuter une recherche IN dans SQL en utilisant Golang?

Qu'est-ce que Go veut pour le deuxième paramètre de cette requête SQL ... Je tente d'utiliser la recherche IN dans postgres 

stmt, err := db.Prepare("SELECT * FROM awesome_table WHERE id= $1 AND other_field IN $2")
rows, err := stmt.Query(10, ???)

Ce que je veux vraiment:

SELECT * FROM awesome_table WHERE id=10 AND other_field IN (this, that);
35
a.m.

Query demande juste varargs pour remplacer les params de votre sqlso, dans votre exemple,

rows, err := stmt.Query(10)

dire, ceci et celui de votre deuxième exemple étaient dynamiques, alors vous feriez

stmt, err := db.Prepare("SELECT * FROM awesome_table WHERE id=$1 AND other_field IN ($2, $3)")
rows, err := stmt.Query(10,"this","that")

Si vous avez des arguments variables pour la partie "IN", vous pouvez faire ( jouer )

package main

import "fmt"
import "strings"

func main() {
    stuff := []interface{}{"this", "that", "otherthing"}
    sql := "select * from foo where id=? and name in (?" + strings.Repeat(",?", len(stuff)-1) + ")"
    fmt.Println("SQL:", sql)
    args := []interface{}{10}
    args = append(args, stuff...)
    fakeExec(args...)
    // This also works, but I think it's harder for folks to read
    //fakeExec(append([]interface{}{10},stuff...)...)
}

func fakeExec(args ...interface{}) {
    fmt.Println("Got:", args)
}
40
David Budworth

Il semble que vous utilisiez le pilote pq . pq a récemment ajouté le support Array spécifique à Postgres via pq.Array (voir demande d'extraction 466 ). Vous pouvez obtenir ce que vous voulez via:

stmt, err := db.Prepare("SELECT * FROM awesome_table WHERE id= $1 AND other_field = ANY($2)")
rows, err := stmt.Query(10, pq.Array([]string{'this','that'})

Je pense que cela génère le SQL:

SELECT * FROM awesome_table WHERE id=10 AND other_field = ANY('{"this", "that"}');

Notez que ceci utilise des instructions préparées, les entrées doivent donc être désinfectées.

27
Pete

Si quelqu'un comme moi essayait d'utiliser un tableau avec une requête, voici une solution simple.

get https://github.com/jmoiron/sqlx

ids := []int{1, 2, 3}
q,args,err := sqlx.In("SELECT id,username FROM users WHERE id IN(?);", ids) //creates the query string and arguments
//you should check for errors of course
q = sqlx.Rebind(sqlx.DOLLAR,q) //only if postgres
rows, err := db.Query(q,args...) //use normal POSTGRES/ANY SQL driver important to include the '...' after the Slice(array)
16
Krtko

Avec PostgreSQL, au moins, vous avez la possibilité de transmettre l’ensemble du tableau sous forme de chaîne, en utilisant un seul espace réservé:

db.Query("select 1 = any($1::integer[])", "{1,2,3}")

De cette façon, vous pouvez utiliser une seule chaîne de requête et toute la concaténation de chaîne est limitée au paramètre. Et si le paramètre est mal formé, vous ne recevez pas d'injection SQL; vous obtenez juste quelque chose comme: ERROR: syntaxe d'entrée invalide pour l'entier: "xyz"

https://groups.google.com/d/msg/golang-nuts/vHbg09g7s2I/RKU7XsO25SIJ

11
Ivan Rave

Plutôt piéton et à n'utiliser que si le serveur est généré. Où UserIDs est une tranche (liste) de chaînes:

sqlc := `select count(*) from test.Logins where UserID 
                in ("` + strings.Join(UserIDs,`","`) + `")`
errc := db.QueryRow(sqlc).Scan(&Logins)
0
user2099484

Vous pouvez également utiliser cette conversion directe.

awesome_id_list := []int{3,5,8}

var str string
for _, value := range awesome_id_list {
        str += strconv.Itoa(value) + ","
}

query := "SELECT * FROM awesome_table WHERE id IN (" + str[:len(str)-1] + ")"

ATTENTION
Cette méthode est vulnérable à l’injection SQL. Utilisez cette méthode uniquement si awesome_id_list est généré par le serveur.

0
Thellimist