Qt - Come legare una QList a una qsqlquery con una clausola "dove ... in"?
-
13-09-2020 - |
Domanda
Nota: questo è con SQLite, anche se mi aspetto che il problema sia sul lato QT.
In primo luogo, ho impostato una tabella di database dallo strumento della riga di comando 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);
.
Allora metto alla prova la mia query:
sqlite> SELECT id,state FROM testtable WHERE state IN (0,1,2);
1|0
3|1
.
(quelli sono previsti risultati.)
Allora eseguo questo codice 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";
}
.
Che stampa questo:
.Prima
Dopo
Nessuna riga è stata stampata.Suppongo che questo sia perché non posso associare un elenco direttamente a un segnaposto in una clausola "in".Ma c'è un modo per farlo?Non sono stato in grado di trovare nulla a riguardo.
Soluzione
Non importa la mia domanda.Penso che cosa sto cercando di fare non è possibile con dichiarazioni preparate, indipendentemente dal quadro o dal RDBMS.Puoi fare "dove x in (?)", Ma allora il "?"Si riferisce a un singolo valore - non può essere un elenco di valori;o puoi fare "dove x in (?,?,?), E ogni '?'deve essere vincolato separatamente.
Esempio:
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();
. Altri suggerimenti
Ho cercato un modo per farlo anche per un po 'ora, e Google non era molto utile.Ho iniziato a giocare con esso e si scopre che è davvero possibile, almeno in misura limitata.È testato solo con PostgreSQL e SQLite, quindi non so di altri RDBMS.Il mio caso riguarda solo i tasti interi, ma dovrebbe funzionare teoricamente per altri tipi.
Il modo per farlo è costruire un array manualmente e legarlo a una variabile.Dì che voglio selezionare più utenti dai loro generatori di generatori da una tabella, come id
.Ecco come può essere fatto.
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();
}
.
Digitato dalla memoria, ma dovrebbe andare bene.So che questa risposta è estremamente tardi, ma spero che questo post aiuti a qualcun altro là fuori.Lo snippet sopra funziona solo con PostgreSQL.Tuttavia è possibile adattarsi anche ad altri database, a seconda del loro supporto dell'array.
per SQLite Sostituisci la query SQL con:
sql.prepare("SELECT id, firstname, lastname FROM users WHERE id IN (:id)");
. Devi usare qsqlquery :: execbatch