Qt - Как связать QList с QSqlQuery с помощью предложения "WHERE ... IN"? - PullRequest
12 голосов
/ 10 июля 2010

Примечание: это с 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».Но есть ли способ сделать это?Я не смог ничего найти по этому поводу.

Ответы [ 3 ]

7 голосов
/ 10 июля 2010

Не берите в голову мой вопрос.Я думаю, что то, что я пытаюсь сделать, невозможно с подготовленными утверждениями, независимо от структуры или РСУБД.Вы можете сделать «ГДЕ x IN (?)», Но затем «?»относится к одному значению - это не может быть список значений;или вы можете сделать "ГДЕ х IN (?,?,?), и каждый '?"нужно связать отдельно.

6 голосов
/ 16 декабря 2013

Я тоже некоторое время искал способ сделать это, и Google не очень помог.Я начал играть с этим, и оказалось, что это действительно возможно, по крайней мере, в ограниченной степени.Я проверил это только с PostgreSQL, поэтому я не знаю о других RDBMS.Мой случай касается только целочисленных ключей, но теоретически должен работать и для других типов.
Способ сделать это - создать массив вручную и связать его с переменной.Скажем, я хочу выбрать нескольких пользователей по их 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.Однако может быть возможно адаптировать это и к другим базам данных, в зависимости от их поддержки массива.

2 голосов
/ 24 октября 2018

Вы должны использовать 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();
...