web-dev-qa-db-ja.com

SQLite:値のリストを "WHERE col IN(:PRM)"にバインドします

私がしたいのは、次のようなクエリを送信することだけです

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');

と役に立たない(2つの追加の単一引用符に注意してください)。私はすでに文字列に余分な 'を入れようとしましたが、エスケープされます。エスケープをオフにするか、テキストが単一引用符で囲まれるのを防ぐオプションが見つかりませんでした。私が考えることができる最後のことは、準備されたステートメントを使用しないことですが、私はそれを最後の選択肢とするだけです。アイデアや提案はありますか?

ありがとう

編集:

パラメータの数は動的であるため、上記の例のように、1つまたは12の3つの数値になる場合があります。

30
Sebastian

次の形式のパラメータ化されたSQLステートメントを動的に構築できます

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

そして、「?」ごとに1回、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.
26
Larry Lustig

私は自分自身でこの質問に直面しましたが、一時テーブルを作成し、それにすべての値を挿入することで答えました。

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

さらに簡単に、次のようにクエリを作成します。

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

配列を1つのパラメーターとして渡すことはできませんが、各配列の値を個別のパラメーター(IN (?, ?, ?))として渡すことはできます。

動的数値パラメーターに対してこれを行う安全な方法(文字列連結、.format()などを使用して、値自体をクエリに挿入しないでください。SQLインジェクションにつながる可能性があります)は、クエリ文字列を生成することです必要な数の?プレースホルダー、次に配列要素をバインドします。配列連結または拡散構文を使用します(*または...(ほとんどの言語)。他のパラメータも渡す必要がある場合。

Python 3の例を次に示します。

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

あなたはこれを試すことができます

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

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

同じ機能に取り組んでいると、このアプローチにつながります:(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

これも問題なく動作します(Javascript ES6)

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

より単純で安全な答えは、単に(クエリのデータ部分ではなく)マスクを生成し、SQLインジェクションフォーマッターエンジンがその仕事を行えるようにすることです。

配列にいくつかのidsがあり、いくつかの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

たとえば、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
pgalilea