18

注意:这是使用 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”子句中的占位符。但是有没有办法做到这一点?我无法找到任何关于此的信息。

4

3 回答 3

9

别管我的问题。我认为无论框架或 RDBMS 如何,使用准备好的语句都无法实现我想要做的事情。您可以执行“WHERE x IN (?)”,然后执行“?” 指单个值——它不能是值列表;或者你可以做“WHERE x IN (?,?,?), and each '?' 需要单独绑定。

例子:

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();
于 2010-07-10T18:38:36.337 回答
8

我也一直在寻找一种方法来做到这一点,而谷歌并不是很有帮助。我开始玩弄它,事实证明这确实是可能的,至少在有限的程度上。它仅使用 PostgreSQL 和 SQLite 进行测试,因此我不了解其他 RDBMS。我的案例只涉及整数键,但理论上也应该适用于其他类型。
这样做的方法是手动构建一个数组并将其绑定到一个变量。假设我想通过他们id的 s 从表中选择多个用户,例如SELECT id, firstname, lastname FROM users WHERE id = ANY(: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)");
于 2013-12-16T08:06:16.903 回答
0

你必须使用QSqlQuery::execBatch

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();
于 2018-10-24T08:45:34.333 回答