Question

Note:c'est avec SQLite, même si je pense que le problème vient du côté Qt.

Tout d'abord, j'ai configuré une table de base de données à partir de l'outil de ligne de commande 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);

Ensuite je teste ma requête :

sqlite> SELECT id,state FROM testtable WHERE state IN (0,1,2);
1|0
3|1

(Ce sont des résultats attendus.)

Ensuite, j'exécute ce code 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";
}

qui imprime ceci :

avant
après

Aucune ligne n'a été imprimée.Je suppose que c'est parce que je ne peux pas lier une liste directement à un espace réservé dans une clause "in".Mais y a-t-il un moyen de le faire ?Je n'ai rien trouvé à ce sujet.

Était-ce utile?

La solution

Peu importe ma question.Je pense que ce que j'essaie de faire n'est pas possible avec des déclarations préparées, quel que soit le cadre ou le SGBDM.Vous pouvez faire "où x dans (?)", Mais alors le "?"se réfère à une seule valeur - il ne peut pas être une liste de valeurs;Ou vous pouvez faire "où x in (?,?,?), et chacun"? "doit être lié séparément.

Exemple:

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();

Autres conseils

Je cherchais également un moyen de le faire depuis un moment maintenant, et Google n'a pas été très utile.J'ai commencé à jouer avec et il s'avère que c'est effectivement possible, du moins dans une certaine mesure.Il est testé uniquement avec PostgreSQL et SQLite, donc je ne connais pas les autres SGBDR.Mon cas concerne uniquement les clés entières, mais devrait théoriquement fonctionner également pour d'autres types.
La façon de procéder consiste à créer un tableau manuellement et à le lier à une variable.Supposons que je souhaite sélectionner plusieurs utilisateurs en fonction de leur ids à partir d'une table, comme SELECT id, firstname, lastname FROM users WHERE id = ANY(:id).Voici comment procéder.

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();
}

Tapé de mémoire, mais ça devrait aller.Je sais que cette réponse est extrêmement tardive, mais j'espère que ce message aidera quelqu'un d'autre.L'extrait ci-dessus ne fonctionne qu'avec PostgreSQL.Cependant, il est également possible de l'adapter à d'autres bases de données, en fonction de leur support de tableau.

Pour SQLite, remplacez la requête SQL par :

sql.prepare("SELECT id, firstname, lastname FROM users WHERE id IN (:id)");

Vous devez utiliser QSQLQUERY :: EXECTBATCH

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();

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top