SQLite:将值列表绑定到“WHERE col IN(:PRM)”

时间:2011-01-25 00:17:15

标签: sqlite select prepared-statement bind

我想做的就是发送一个像

这样的查询
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');

并且没用(请注意另外两个单引号)。我已经尝试在字符串中添加额外的'但它们会被转义。我没有找到关闭转义或防止文本被单引号括起来的选项。我能想到的最后一件事是没有使用准备好的声明,但我只把它作为最后一个选项。你有什么想法或建议吗?

由于

编辑:

参数的数量是动态的,因此它可能是三个数字,如上例所示,一个或十二个。

11 个答案:

答案 0 :(得分:26)

您可以动态构建表单

的参数化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.

答案 1 :(得分:9)

我自己刚刚面对这个问题,但是通过创建一个临时表并将所有值插入其中来回答它,以便我可以这样做:

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

答案 2 :(得分:6)

更简单,建立您的查询:

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

答案 3 :(得分:2)

根据您的 sqlite 构建(它不是默认构建的一部分),您可以使用:

SELECT * FROM table WHERE col IN carray(?42);

然后使用(假设是 C API)绑定 ?42

int32_t data[] = {110, 130, 90};
sqlite3_carray_bind(
    stmtPtr, 42,
    data, sizeof(data)/sizeof(data[0]),
    CARRAY_INT32, SQLITE_TRANSIENT);

我还没有实际测试过,我只是阅读了文档:https://sqlite.org/carray.html

答案 4 :(得分:1)

您不能将数组作为一个参数传递,但可以将每个数组值作为单独的参数(IN (?, ?, ?))传递。

对动态数字参数执行此操作的安全方法(不应该使用字符串串联,.format()等将值本身插入查询中,这可能导致SQL注入)是生成查询具有所需数量的?占位符的字符串,然后绑定数组元素。如果还需要传递其他参数,请使用数组串联或扩展语法(在大多数语言中为*...)。

以下是Python 3的示例:

c.execute('SELECT * FROM TABLE WHERE col IN ({}) LIMIT ?'
       .format(', '.join(['?'] * len(values))), [*values, limit])

答案 5 :(得分:0)

使用相同的功能引导我采用这种方法: (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();
            });
        });
    };

答案 6 :(得分:0)

例如,如果你想要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 )

答案 7 :(得分:0)

这很好用(Javascript ES6)

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

答案 8 :(得分:0)

一个更简单,更安全的答案只涉及生成掩码(与查询的数据部分相对)并允许SQL注入格式化程序引擎完成其工作。

假设我们在数组中有一些id,并且有一些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);

答案 9 :(得分:0)

您可以尝试

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

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

答案 10 :(得分:0)

我的节点解决方案(ES6,Promises):

let records = await db.all(`
    SELECT * FROM table
    WHERE (column1 = ?) and column2 IN ( ${[...val2s].fill('?').join(',')} )
`, [val1, ...val2s])

适用于可变数量的可能值。

这使用了 sqlite-async,但您可以为回调样式版本简单地修改它。