Qt - Как связать QList с QSqlQuery с предложением WHERE... IN?
Примечание: это с 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
(Ожидаемые результаты.)
Затем я запускаю этот код на С++:
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". Но есть ли способ сделать это? Я ничего не смог найти об этом.
Ответы
Ответ 1
Не обращай внимания на мой вопрос. Я думаю, что то, что я пытаюсь сделать, невозможно с подготовленными заявлениями, независимо от структуры или РСУБД. Вы можете сделать "WHERE x IN (?)", Но затем "?" относится к одному значению - он не может быть списком значений; или вы можете сделать "WHERE x IN (?,?,?) и каждый"? " необходимо связать отдельно.
Ответ 2
Я искал способ сделать это слишком долго, и Google не очень помог. Я начал играть с ним, и оказалось, что это действительно возможно, в меньшей степени, по крайней мере. Я тестировал его только с PostgreSQL, поэтому я не знаю о других РСУБД. Мой случай касается только целочисленных ключей, но теоретически должен работать и для других типов.
Способ сделать это - построить массив вручную и привязать его к переменной. Скажем, я хочу выбрать несколько пользователей по их id
из таблицы, например 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", QString("{%1}").arg(numberlist));
sql.exec();
// Now this is possible
while( sql.next() ) {
qDebug() << sql.value(0).toInt() << sql.value(1).toString() << sql.value(2).toString();
}
Набирается из памяти, но должно быть хорошо. Я знаю, что этот ответ очень поздний, но, надеюсь, этот пост помогает кому-то другому. И, как упоминалось ранее, это работает только с PostgreSQL. Однако, возможно, это можно будет адаптировать к другим базам данных, в зависимости от поддержки их массивов.
Ответ 3
Вы должны использовать 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();