执行 SQL 语句

QSqlQuery 类提供了执行 SQL 语句和浏览查询结果集的接口。

下一节介绍的QSqlQueryModelQSqlTableModel 类为访问数据库提供了更高级别的接口。如果您不熟悉 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()) { QStringname=query.value(0).toString();intsalary=query.value(1).toInt();        qDebug() << name << salary;
    }

QSqlQuery::value() 函数返回当前记录中字段的值。字段指定为基于零的索引。QSqlQuery::value() 返回一个QVariant ,该类型可容纳各种 C++ 和 Qt Core 数据类型,如intQStringQByteArray 。不同的数据库类型会自动映射为最接近的 Qt 对应类型。在代码片段中,我们调用QVariant::toString() 和QVariant::toInt() 将变体转换为QStringint

有关与 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(true)。这是一个简单的优化方法,在操作大型结果集时,可以显著加快查询速度。

插入、更新和删除记录

QSqlQuery SELECT下面的示例使用 向表中插入一条记录: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();

事务可用于确保复杂操作的原子性(例如,查找外键并创建记录),或提供取消中间复杂更改的方法。

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