SQLite: привязать список значений к "WHERE col IN (: PRM)" - PullRequest
29 голосов
/ 25 января 2011

Все, что я хочу сделать, это отправить запрос типа

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

Поэтому я подготовил следующее утверждение

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

Затем я использую

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

К сожалениюэто становится

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

и бесполезно (обратите внимание на две дополнительные одинарные кавычки).Я уже пытался добавить extra 'в строку, но они сбежали.Я не нашел возможности отключить экранирование или запретить заключать текст в одинарные кавычки.Последнее, о чем я могу подумать, - это не использовать подготовленное утверждение, а только последний вариант.У вас есть какие-либо идеи или предложения?

Спасибо

Редактировать:

Число параметров является динамическим, поэтому это может быть три числа, как в примере выше, одинили двенадцать.

Ответы [ 8 ]

26 голосов
/ 25 января 2011

Вы можете динамически построить параметризованный оператор SQL в форме

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

и затем вызывать sqlite_bind_int один раз для каждого "?"Вы добавили в оператор.

Нет способа напрямую связать текстовый параметр с несколькими целочисленными (или, в данном случае, с несколькими текстовыми) параметрами.

Вот псевдокод того, что у меняв уме:

-- 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.
9 голосов
/ 01 июня 2012

Я только что столкнулся с этим вопросом сам, но ответил на него, создав временную таблицу и вставив в нее все значения, чтобы я мог затем сделать:

SELECT * FROM TABLE WHERE col IN (SELECT col FROM temporarytable);
6 голосов
/ 28 марта 2013

Еще проще, создайте свой запрос следующим образом:

"SELECT * FROM TABLE WHERE col IN ("+",".join(["?"]*len(lst))+")"
0 голосов
/ 15 января 2019

Вы можете попробовать это

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

dbGetQuery(db_con, paste0("SELECT * FROM table WHERE col IN (", paste0(shQuote(lst), collapse=", ") , ");"))
0 голосов
/ 03 сентября 2017

Гораздо более простой и безопасный ответ состоит в том, чтобы просто создать маску (в отличие от части данных запроса) и позволить модулю форматирования SQL-инъекций выполнить свою работу.

Предположим, у нас есть id s в массиве и несколько 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 голосов
/ 31 августа 2017

отлично работает, а также (Javascript ES6) :

let myList = [1, 2, 3];
`SELECT * FROM table WHERE col IN (${myList.join()});`
0 голосов
/ 18 августа 2016

Например, если вы хотите запрос sql:

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

Как насчет:

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 голосов
/ 24 июля 2016

Работа над той же функциональностью привела меня к такому подходу: (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();
            });
        });
    };
...