Qt - Как связать QList к 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();
. Другие советы
Я искал способ сделать это тоже некоторое время, и Google не был очень полезен.Я начал играть с ним, и оказывается, это действительно возможно, в ограниченной степени, по крайней мере.Проверено только с PostgreSQL и SQLite, поэтому я не знаю о других RDBMS.Мой дело касается только целочисленных ключей, но следует также теоретически работать для других типов.
Способ сделать это создает массив вручную и связывает его с переменной.Скажем, я хочу выбрать несколько пользователей по своим генеракодицетамCodes из таблицы, такой как 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 :: exchbatch >
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();
.