Pregunta

Nota:Esto es con SQLite, aunque espero que el problema esté en el lado de Qt.

Primero, configuro una tabla de base de datos desde la herramienta de línea de comandos 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);

Luego pruebo mi consulta:

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

(Esos son resultados esperados).

Luego ejecuto este código 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";
}

que imprime esto:

antes
después

No se imprimieron filas.Supongo que esto se debe a que no puedo vincular una lista directamente a un marcador de posición en una cláusula "in".¿Pero hay alguna manera de hacerlo?No he podido encontrar nada sobre esto.

¿Fue útil?

Solución

No importa mi pregunta.Creo que lo que estoy tratando de hacer no es posible con las declaraciones preparadas, independientemente del marco o el RDBMS.Puedes hacer "donde x en (?)", ¿Pero entonces el '?'se refiere a un solo valor: no puede ser una lista de valores;O puedes hacer "¿Dónde x en (?,?,?), ¿Y cada uno? 'necesita estar unido por separado.

Ejemplo:

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

Otros consejos

He estado buscando una manera de hacer esto también desde hace un tiempo y Google no fue de mucha ayuda.Empecé a jugar con ello y resulta que sí es posible, al menos hasta cierto punto.Está probado sólo con PostgreSQL y SQLite, por lo que no conozco otros RDBMS.Mi caso se refiere solo a claves enteras, pero en teoría debería funcionar también para otros tipos.
La forma de hacerlo es crear una matriz manualmente y vincularla a una variable.Digamos que quiero seleccionar varios usuarios por su ids de una mesa, como SELECT id, firstname, lastname FROM users WHERE id = ANY(:id).Así es como se puede hacer.

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

Escrito de memoria, pero debería estar bien.Sé que esta respuesta llega muy tarde, pero espero que esta publicación ayude a alguien más.El fragmento anterior sólo funciona con PostgreSQL.Sin embargo, también es posible adaptar esto a otras bases de datos, dependiendo de su soporte de matriz.

Para SQLite reemplace la consulta SQL con:

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

Tienes que usar 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();

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top