本页内容

执行 SQL 语句

QSqlQuery 类提供了一个用于执行SQL语句并在查询结果集中进行导航的接口。

下一节中介绍的QSqlQueryModel 和QSqlTableModel 类为访问数据库提供了更高层次的接口。如果您不熟悉SQL,不妨直接跳到下一节(使用SQL模型类)。

执行查询

要执行一个 SQL 语句,只需创建一个QSqlQuery 对象,并像这样调用QSqlQuery::exec():

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

QSqlQuery 构造函数接受一个可选的QSqlDatabase 对象,用于指定要使用的数据库连接。在上例中,我们未指定任何连接,因此将使用默认连接。

如果发生错误,exec() 会返回false 。此时可通过QSqlQuery::lastError() 获取该错误。

QSqlQuery 该方法支持逐条访问结果集。调用exec() 之后,QSqlQuery 的内部指针将定位在第一条记录的前一位。 我们必须先调用一次QSqlQuery::next()以跳转到第一条记录,然后反复调用next()来访问其余记录,直到其返回false 。以下是一个按顺序遍历所有记录的典型循环:

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

QSqlQuery::value() 函数返回当前记录中某个字段的值。 字段通过从零开始的索引进行指定。QSqlQuery::value() 返回一个 `QVariant` 对象,该类型可容纳各种 C++ 和 Qt Core 数据类型,例如 `int`、`QString` 以及 `QByteArray`。不同的数据库类型会自动映射为最接近的 Qt 等效类型。在代码片段中,我们调用 `QVariant::toString()` 和 `QVariant::toInt()` 将变体类型转换为 `QString ` 和 `int`。

有关 Qt 支持的数据库中推荐使用的类型的概述,请参阅此表。

您可以使用QSqlQuery::next()、QSqlQuery::previous()、QSqlQuery::first()、QSqlQuery::last() 和QSqlQuery::seek() 在数据集中进行导航。当前行索引由QSqlQuery::at() 返回,对于支持该功能的数据库,结果集中的总行数可通过QSqlQuery::size() 获取。

要确定数据库驱动程序是否支持某项特定功能,请使用QSqlDriver::hasFeature()。在下面的示例中,我们调用QSqlQuery::size() 来确定底层数据库的结果集大小是否支持该功能;否则,我们将跳转到最后一条记录,并利用查询的位置来判断共有多少条记录。

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

如果在结果集内导航,且仅使用 next() 和 seek() 进行向前浏览,则可以在调用 exec() 之前调用QSqlQuery::setForwardOnly()。这是一个简单的优化方法,在处理大型结果集时能显著加快查询速度。

插入、更新和删除记录

QSqlQuery 不仅可以执行SELECT语句,还可以执行任意SQL语句。以下示例使用INSERT 向表中插入一条记录:

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

如果需要同时插入多条记录,通常将查询语句与实际要插入的值分离会更高效。这可以通过使用占位符来实现。Qt 支持两种占位符语法:命名绑定和位置绑定。以下是一个命名绑定的示例:

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

以下是一个位置绑定的示例:

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

这两种语法均可与 Qt 提供的所有数据库驱动程序配合使用。如果数据库原生支持该语法,Qt 会直接将查询转发给数据库管理系统(DBMS);否则,Qt 会通过对查询进行预处理来模拟占位符语法。最终由 DBMS 执行的实际查询可通过QSqlQuery::executedQuery() 获取。

插入多条记录时,只需调用一次QSqlQuery::prepare()。随后,根据需要多次调用bindValue() 或addBindValue(),并紧接着调用exec()。

除了性能优势外,占位符的另一个优点是,您可以轻松指定任意值,而无需担心特殊字符的转义问题。

更新记录与将其插入表中的操作类似:

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

您还可以使用命名绑定或位置绑定,将参数与实际值关联起来。

最后,以下是一个DELETE 语句的示例:

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

事务

如果底层数据库引擎支持事务,QSqlDriver::hasFeature (QSqlDriver::Transactions )将返回 true。您可以使用QSqlDatabase::transaction() 来启动事务,随后执行您希望在事务上下文中执行的 SQL 命令,最后使用QSqlDatabase::commit() 或QSqlDatabase::rollback() 结束事务。在使用事务时,必须在创建查询之前先启动事务。

示例:

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

事务可用于确保复杂操作具有原子性(例如,查询外键并创建记录),或提供一种在操作中途取消复杂更改的机制。

© 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.