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

Seb*_*ian 29 sqlite select bind prepared-statement

我想做的就是发送一个查询

SELECT * FROM table WHERE col IN (110, 130, 90);
Run Code Online (Sandbox Code Playgroud)

所以我准备了以下声明

SELECT * FROM table WHERE col IN (:LST);
Run Code Online (Sandbox Code Playgroud)

然后我用

sqlite_bind_text(stmt, 1, "110, 130, 90", -1, SQLITE_STATIC);
Run Code Online (Sandbox Code Playgroud)

不幸的是,这变成

SELECT * FROM table WHERE col IN ('110, 130, 90');
Run Code Online (Sandbox Code Playgroud)

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

谢谢

编辑:

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

Lar*_*tig 26

您可以动态构建表单的参数化SQL语句

 SELECT * FROM TABLE WHERE col IN (?, ?, ?)
Run Code Online (Sandbox Code Playgroud)

然后为每个"?"调用一次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.
Run Code Online (Sandbox Code Playgroud)

  • 不,您每次都必须准备声明。如果不知道 IN () 子句中有多少个值(该信息可能有助于执行计划),则无法准备语句。 (2认同)

hat*_*nch 9

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

SELECT * FROM TABLE WHERE col IN (SELECT col FROM temporarytable);
Run Code Online (Sandbox Code Playgroud)


xti*_*tin 6

更简单,像这样构建您的查询:

"SELECT * FROM TABLE WHERE col IN ("+",".join(["?"]*len(lst))+")"
Run Code Online (Sandbox Code Playgroud)

  • 这种解决方案应该始终带有安全警告:如果“lst”有可能不是绝对干净的数据(即它已被用户接触过......),那么系统可能容易受到 SQL 注入的攻击这样的方法。 (5认同)
  • 这是蟒蛇.你在找什么语言? (4认同)
  • @Stabledog:此示例使用准备好的语句。SQL 仅取决于列表的长度,而不取决于内容。它可能是一个 DOS 向量,但它不是一个任意的 SQL 注入向量。 (2认同)

BCS*_*BCS 6

根据您的 sqlite 版本(它不是默认版本的一部分),您也许可以使用:

SELECT * FROM table WHERE col IN carray(?42);
Run Code Online (Sandbox Code Playgroud)

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

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

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


bur*_*yan 6

一种解决方案(我尚未在代码中尝试过,但仅在 SQLite shell 上尝试过)是使用json_eachSQLite 中的函数。

所以你可以这样做:

SELECT * FROM table
WHERE col IN (SELECT value FROM json_each(?));
Run Code Online (Sandbox Code Playgroud)

需要注意的是,您必须手动将有效的 JSON 数组与您尝试绑定的值组装在一起。