web-dev-qa-db-fra.com

SQLite: lier la liste de valeurs à "WHERE col IN (: PRM)"

tout ce que je veux faire est d'envoyer une requête comme

SELECT * FROM table WHERE col IN (110, 130, 90);

J'ai donc préparé la déclaration suivante

SELECT * FROM table WHERE col IN (:LST);

Alors j'utilise 

sqlite_bind_text(stmt, 1, "110, 130, 90", -1, SQLITE_STATIC);

Malheureusement cela devient

SELECT * FROM table WHERE col IN ('110, 130, 90');

et est inutile (notez les deux guillemets simples supplémentaires). J'ai déjà essayé de mettre extra 'dans la chaîne mais ils se sont échappés. Je n'ai pas trouvé une option pour désactiver l'échappement ou empêcher le texte d'être entouré de guillemets simples. La dernière chose à laquelle je peux penser est de ne pas utiliser une déclaration préparée, mais je la prendrais uniquement comme dernière option. Avez-vous des idées ou des suggestions?

Merci

Modifier:

Le nombre de paramètres est dynamique, il peut donc s'agir de trois nombres, comme dans l'exemple ci-dessus, un ou douze.

28
Sebastian

Vous pouvez créer dynamiquement une instruction SQL paramétrée de la forme

 SELECT * FROM TABLE WHERE col IN (?, ?, ?)

puis appelez sqlite_bind_int une fois pour chaque "?" vous avez ajouté à la déclaration.

Il n’existe aucun moyen de lier directement un paramètre de texte à plusieurs paramètres entiers (ou même multiples texte).

Voici un pseudo-code pour ce que j'ai en tête:

-- Args is an array of parameter values
for i = Lo(Args) to Hi(Args)
   paramlist = paramlist + ', ?'

sql = 'SELECT * FROM TABLE WHERE col IN (' + Right(paramlist, 3)  + ')'

for i = Lo(Args) to Hi(Args)
  sql_bind_int(sql, i, Args[i]

-- execute query here.
26
Larry Lustig

J'ai moi-même fait face à cette question, mais j'y ai répondu en créant une table temporaire et en y insérant toutes les valeurs afin que je puisse ensuite:

SELECT * FROM TABLE WHERE col IN (SELECT col FROM temporarytable);
9
hatfinch

Encore plus simple, construisez votre requête comme ceci:

"SELECT * FROM TABLE WHERE col IN ("+",".join(["?"]*len(lst))+")"
6
xtin

Tu peux essayer ça

RSQLite in R:
lst <- c("a", "b", "c")

dbGetQuery(db_con, paste0("SELECT * FROM table WHERE col IN (", paste0(shQuote(lst), collapse=", ") , ");"))
0
Ksenia

Travailler sur une même fonctionnalité m'a conduit à cette approche: (nodejs, es6, Promise)

    var deleteRecords = function (tblName, data) {
        return new Promise((resolve, reject) => {
            var jdata = JSON.stringify(data);
            this.run(`DELETE FROM ${tblName} WHERE id IN (?)`, jdata.substr(1, jdata.length - 2), function (err) {
                err ? reject('deleteRecords failed with : ' + err) : resolve();
            });
        });
    };
0
Reza Afzalan

cela fonctionne aussi bien (Javascript ES6) :

let myList = [1, 2, 3];
`SELECT * FROM table WHERE col IN (${myList.join()});`
0
Moritz

Une réponse beaucoup plus simple et plus sûre consiste simplement à générer le masque (par opposition à la partie données de la requête) et à laisser le moteur de formateur d'injection SQL faire son travail.

Supposons que nous ayons des noms ids dans un tableau et des rappels cb:

/* we need to generate a '?' for each item in our mask */
const mask = Array(ids.length).fill('?').join();

db.get(`
  SELECT *
    FROM films f
   WHERE f.id
      IN (${mask})
`, ids, cb);
0
jasonseminara

Par exemple, si vous voulez la requête SQL:

select * from table where col in (110, 130, 90)

Qu'en est-il de:

my_list = [110, 130, 90]
my_list_str = repr(my_list).replace('[','(').replace(']',')') 
cur.execute("select * from table where col in %s" % my_list_str )
0
pgalilea