QT - QlistをQSQLQueryに "WHERE ... IN"句を指定してバインドする方法
-
13-09-2020 - |
質問
注:これはSQLiteと共にありますが、問題がQT側にあることを期待していますが。
まず、SQLiteコマンドラインツールからデータベーステーブルを設定します。
sqlite> create table testtable ( id INTEGER PRIMARY KEY NOT NULL, state INTEGER );
sqlite> insert into testtable (state) values (0);
sqlite> insert into testtable (state) values (1);
sqlite> insert into testtable (state) values (9);
sqlite> insert into testtable (state) values (20);
.
それから私のクエリをテストします:
sqlite> SELECT id,state FROM testtable WHERE state IN (0,1,2);
1|0
3|1
.
(それらは期待されています。)
このC ++コードを実行します。
void runQuery() {
QSqlQuery qq;
qq.prepare( "SELECT id,state FROM testtable WHERE state IN (:states)");
QList<QVariant> statesList = QList<QVariant>();
statesList.append(0);
statesList.append(1);
statesList.append(2);
qq.bindValue(":states", statesList);
qq.exec();
qDebug() << "before";
while( qq.next() ) {
qDebug() << qq.value(0).toInt() << qq.value(1).toInt();
}
qDebug() << "after";
}
.
これを印刷する:
前の
の後
行が印刷されていない。これが、「IN」句のプレースホルダに直接リストをバインドできないためです。しかし、それをする方法はありますか?私はこれについて何も見つけることができなかった。
解決
私の質問を気にしないでください。フレームワークやRDBMSに関係なく、準備がしようとしていることはできません。あなたはできることをすることができます "x in(?)"ですが、その後 '?'単一の値を参照します - それは値のリストになることはできません。それともあなたはできることをすることができます(?、?、?、?)、そしてそれぞれの「?」別々に連結する必要があります。
例:
QString const queryText = "SELECT id, firstname FROM users WHERE id IN (%1)";
QVector<int> const ids { /* ... */ };
QVector<QString> const placeholders(ids.size(), "?");
QSqlQuery query(db);
query.prepare(queryText.arg(QStringList::fromVector(placeholders).join(", ")));
for (auto const & i : ids)
query.addBindValue(i);
query.exec();
. 他のヒント
私は今の間もこれを行う方法を探しています、そしてグーグルはそれほど役に立ちませんでした。私はそれと一緒に遊んで遊んで、少なくとも限られた程度の程度にそれが可能であることがわかりました。PostgreSQLとSQLiteのみでテストされているので、他のRDBMSについてはわかりません。私の事件は整数キーのみを懸念しますが、理論的には他のタイプのために働くべきです。
これを行う方法は、手動で配列を作成し、それを変数にバインドします。id
などのテーブルからのSELECT id, firstname, lastname FROM users WHERE id = ANY(:id)
sで複数のユーザーを選択したいとします。これがどのように行うことができるかです。
QList<int> ids; // A list of IDs to select
ids << 1 << 5 << 7;
// Create strings from list
QStringList idstrings;
foreach(int id, ids) {
idstrings << QString::number(id);
}
QString numberlist = idstrings.join(",");
// Create, prepare and execute the query
QSqlQuery sql;
sql.prepare("SELECT id, firstname, lastname FROM users WHERE id = ANY(:id)");
sql.bindValue(":id", numberlist);
sql.exec();
// Now this is possible
while( sql.next() ) {
qDebug() << sql.value(0).toInt() << sql.value(1).toString() << sql.value(2).toString();
}
.
メモリからタイプされていますが、大丈夫です。私はこの返事が非常に遅くなっていることを知っていますが、うまくいけばこの記事は他の誰かを助けます。上記のスニペットはPostgreSQLでのみ動作します。しかし、アレイサポートに応じて、これを他のデータベースにも適応させることが可能です。
SQLiteの場合、SQLクエリを:
sql.prepare("SELECT id, firstname, lastname FROM users WHERE id IN (:id)");
.