En esta página

Ejecución de Sentencias SQL

La clase QSqlQuery proporciona una interfaz para ejecutar sentencias SQL y navegar por el conjunto de resultados de una consulta.

Las clases QSqlQueryModel y QSqlTableModel descritas en la siguiente sección proporcionan una interfaz de nivel superior para acceder a bases de datos. Si no está familiarizado con SQL, puede pasar directamente a la siguiente sección(Uso de las clases del modelo SQL).

Ejecución de una consulta

Para ejecutar una sentencia SQL, simplemente cree un objeto QSqlQuery y llame a QSqlQuery::exec() de la siguiente manera:

    QSqlQuery query;
    query.exec("SELECT name, salary FROM employee WHERE salary > 50000");

El constructor QSqlQuery acepta un objeto opcional QSqlDatabase que especifica la conexión de base de datos a utilizar. En el ejemplo anterior, no especificamos ninguna conexión, por lo que se utiliza la conexión por defecto.

Si se produce un error, exec() devuelve false. El error está entonces disponible como QSqlQuery::lastError().

QSqlQuery permite acceder al conjunto de resultados registro a registro. Tras la llamada a exec(), el puntero interno de QSqlQuery se encuentra una posición antes del primer registro. Debemos llamar a QSqlQuery::next() una vez para avanzar hasta el primer registro, y luego a next() repetidamente para acceder a los demás registros, hasta que devuelva false. He aquí un bucle típico que itera sobre todos los registros en orden:

   while (query.next()) { QString name = query.value(0).toString(); int salary = query.value(1).toInt();        qDebug() << name << salary;
    }

La función QSqlQuery::value() devuelve el valor de un campo del registro actual. Los campos se especifican como índices basados en cero. QSqlQuery::value() devuelve un QVariant, un tipo que puede contener varios tipos de datos de C++ y del núcleo de Qt, como int, QString y QByteArray. Los diferentes tipos de base de datos se mapean automáticamente en el equivalente Qt más cercano. En el fragmento de código, llamamos a QVariant::toString() y QVariant::toInt() para convertir las variantes a QString y int.

Para obtener una visión general de los tipos recomendados para su uso con bases de datos compatibles con Qt, consulte esta tabla.

Puede navegar dentro del conjunto de datos utilizando QSqlQuery::next(), QSqlQuery::previous(), QSqlQuery::first(), QSqlQuery::last() y QSqlQuery::seek(). El índice de la fila actual se devuelve mediante QSqlQuery::at(), y el número total de filas del conjunto de resultados está disponible como QSqlQuery::size() para las bases de datos que lo admiten.

Para determinar si un controlador de base de datos admite una función determinada, utilice QSqlDriver::hasFeature(). En el siguiente ejemplo, llamamos a QSqlQuery::size() para determinar el tamaño de un conjunto de resultados si la base de datos subyacente admite esa característica; de lo contrario, navegamos hasta el último registro y utilizamos la posición de la consulta para saber cuántos registros hay.

    QSqlQuery query;
    int numRows;
    query.exec("SELECT name, salary FROM employee WHERE salary > 50000");

    QSqlDatabase defaultDB = QSqlDatabase::database();
    if (defaultDB.driver()->hasFeature(QSqlDriver::QuerySize)) {
        numRows = query.size();
    } else {
        // this can be very slow
        query.last();
        numRows = query.at() + 1;
    }

Si navega dentro de un conjunto de resultados, y utiliza next() y seek() sólo para navegar hacia adelante, puede llamar a QSqlQuery::setForwardOnly(true) antes de llamar a exec(). Se trata de una optimización sencilla que acelerará significativamente la consulta cuando se trabaje con conjuntos de resultados grandes.

Inserción, actualización y eliminación de registros

QSqlQuery puede ejecutar sentencias SQL arbitrarias, no sólo SELECTs. El siguiente ejemplo inserta un registro en una tabla utilizando INSERT:

    QSqlQuery query;
    query.exec("INSERT INTO employee (id, name, salary) "
               "VALUES (1001, 'Thad Beaumont', 65000)");

Si desea insertar muchos registros al mismo tiempo, a menudo es más eficiente separar la consulta de los valores reales que se insertan. Esto puede hacerse utilizando marcadores de posición. Qt soporta dos sintaxis de marcadores de posición: named binding y positional binding. A continuación se muestra un ejemplo:

    QSqlQuery query;
    query.prepare("INSERT INTO employee (id, name, salary) "
                  "VALUES (:id, :name, :salary)");
    query.bindValue(":id", 1001);
    query.bindValue(":name", "Thad Beaumont");
    query.bindValue(":salary", 65000);
    query.exec();

Este es un ejemplo de vinculación posicional:

    QSqlQuery query;
    query.prepare("INSERT INTO employee (id, name, salary) "
                  "VALUES (?, ?, ?)");
    query.addBindValue(1001);
    query.addBindValue("Thad Beaumont");
    query.addBindValue(65000);
    query.exec();

Ambas sintaxis funcionan con todos los controladores de bases de datos proporcionados por Qt. Si la base de datos soporta la sintaxis de forma nativa, Qt simplemente reenvía la consulta al SGBD; en caso contrario, Qt simula la sintaxis posicional preprocesando la consulta. La consulta real que acaba siendo ejecutada por el SGBD está disponible como QSqlQuery::executedQuery().

Cuando se insertan varios registros, sólo es necesario llamar una vez a QSqlQuery::prepare(). A continuación, llame a bindValue() o addBindValue() seguido de exec() tantas veces como sea necesario.

Además del rendimiento, una ventaja de los marcadores de posición es que se pueden especificar fácilmente valores arbitrarios sin tener que preocuparse de escapar caracteres especiales.

Actualizar un registro es similar a insertarlo en una tabla:

    QSqlQuery query;
    query.exec("UPDATE employee SET salary = 70000 WHERE id = 1003");

También puede utilizar la vinculación por nombre o por posición para asociar parámetros a valores reales.

Por último, he aquí un ejemplo de sentencia DELETE:

    QSqlQuery query;
    query.exec("DELETE FROM employee WHERE id = 1007");

Transacciones

Si el motor de base de datos subyacente admite transacciones, QSqlDriver::hasFeature(QSqlDriver::Transactions) devolverá verdadero. Puede utilizar QSqlDatabase::transaction() para iniciar una transacción, seguido de los comandos SQL que desee ejecutar en el contexto de la transacción y, a continuación, QSqlDatabase::commit() o QSqlDatabase::rollback(). Cuando utilice transacciones debe iniciar la transacción antes de crear su consulta.

Ejemplo:

    QSqlDatabase::database().transaction();
    QSqlQuery query;
    query.exec("SELECT id FROM employee WHERE name = 'Torild Halvorsen'");
    if (query.next()) {
        int employeeId = query.value(0).toInt();
        query.exec("INSERT INTO project (id, name, ownerid) "
                   "VALUES (201, 'Manhattan Project', "
                   + QString::number(employeeId) + ')');
    }
    QSqlDatabase::database().commit();

Las transacciones pueden utilizarse para garantizar que una operación compleja sea atómica (por ejemplo, buscar una clave foránea y crear un registro), o para proporcionar un medio de cancelar un cambio complejo en el medio.

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.