Qt - 如何将qlist绑定到qsqlquery的qsqlquery,其中包含“在其中...中”条款?
-
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";
}
.
哪个打印:
之前 在
之后
没有打印行。我认为这是因为我不能将列表直接绑定到“在”子句中的占位符。但有没有办法做到这一点?我没有能够找到关于这个的事情。
解决方案
别介意我的问题。我认为,无论框架或RDBMS如何,我都不可能做到的是不可能的。你可以做“哪里x在(?)”,但然后是'?'指单个值 - 它不能是值列表;或者你可以做“在哪里X进入(?,?,?)和每个'?'?'需要单独约束。
示例:
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
。这是如何完成的。
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)");
. 你必须使用 qsqlquery :: exectbatch
QSqlQuery q;
q.prepare("insert into myTable values (?, ?)");
QVariantList ints;
ints << 1 << 2 << 3 << 4;
q.addBindValue(ints);
QVariantList names;
names << "Harald" << "Boris" << "Trond" << QVariant(QVariant::String);
q.addBindValue(names);
if (!q.execBatch())
qDebug() << q.lastError();
. 不隶属于 StackOverflow