QSqlQuery 类为执行SQL语句和浏览查询结果上提供了交互接口。
QSqlQueryModel 和QSqlTableModel在访问数据库上提供了更抽象的接口,这两个类将在下一部分进行说明。如果你不熟悉SQL,那么你可以直接查看下一部分
Using the SQL Model Class 。
执行一条语句
要执行一条SQL语句,你可以创建一个QSqlQuery 对象,然后调用 QSqlQuery:exec() 函数,如下:
QSqlQuery query; |
QSqlQuery 的构造函数接受一个可选的QSqlDatabase对象作为参数,用来指定要使用的数据库。在上述例子中,QSqlQuery 对象在构造时没有传参来指定数据库,所以会使用默认的数据库连接。如果发生了错误,exec() 函数会返回false。之后可以使用 QSqlQuery:lastError() 函数来查看错误。
浏览查询结果
QSqlQuery 类可以逐一访问结果集的每一条记录。在调用 exec() 函数后,QSqlQuery 的内部指针会指向第一条记录之前的位置。我们必须调用 QSqlQuery:next() 函数将指针指向第一条记录,之后通过反复调用 next() 函数来获取其他记录,直到 next() 函数返回false。以下是一个典型的循环来遍历所有记录:
while (query.next()) { |
QSqlQuery:value() 函数返回当前记录的指定字段的值。字段从0开始进行索引。 QSqlQuery::value() 函数返回一个QVariant类对象,它支持各种C++和Qt的核心数据类型,例如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() 函数可以确定一个数据库是否支持给定的特性。在下面的例子中,如果数据库支持size特性,通过调用 QSqlQuery:size() 函数来获取结果集的记录数,不然,通过访问最后一条记录,利用记录的位置来总的记录数。
QSqlQuery query; |
如果你在遍历结果时只通过传递正整数值来调用函数 next(), _seek()_,那么,你可以在调用 exec() 函数前,调用 _QSqlQuery::setForwardOnly(true)_。在针对大数据结果集进行操作时,这个简单的做法会显著的加快查询的速度。
插入,更新,删除记录
QSqlQuery 类可以执行任意的SQL语句,不单单是select。下面的例子说明了如何使用insert 将一条记录插入数据表中:
QSqlQuery query; |
如果你想要同时插入多条记录,那么将真实的数据和SQL语句分开是一种比较有效的做法。这就要用到占位符。Qt支持两种占位符语法:命名绑定和位置绑定。下面是命名绑定的例子:
QSqlQuery query; |
位置绑定示例:
QSqlQuery query; |
以上两种语法在Qt支持的数据库中都是有效的。如果数据库本就支持上述语法,那么Qt就会简单的将语句转发给数据库系统进行执行;否则,Qt会通过预处理查询来模拟占位符语法。最后,数据库执行的真正语句可以通过 QSqlQuery:executedQuery() 函数获得。需要插入多条记录时,只需要提前调用一次 QSqlQuery:prepare() 函数。之后你可以在调用 exec() 函数之前,根据需要调用 bindValue() 或者 addBindValue() 函数。除了性能,使用占位符的另外一个优点在于,你可以指定任意值而不用担心转义字符的问题。
更新一条记录和插入记录类似:
QSqlQuery query; |
你同样可以使用命名绑定或者位置绑定将参数值和真值关联起来。
最后,这是删除语句的例子:
QSqlQuery query; |
事务处理
如果基础数据库引擎支持事务处理,那么 QSqlDriver::hasFeature(QSqlDriver::Transactions) 函数的返回值为true。首先使用 QSqlDatabase::transaction() 来启动事务,其次为要执行的SQL命令,最后调用 QSqlDatabase::commit() 或者 QSqlDatabase::rollback() 函数。当使用事务创建查询之前,首先要启动事务。
例子:
QSqlDatabase::database().transaction(); |
事务机制的使用是用来保证一个复杂操作的原子性(举个例子,查询一个外键和增加一条记录),或是提供一种消除中间复杂性变化的手段。
Qt SQL Programming 系列翻译
- SQL Programming (1): Overview
- SQL Programming (2): Connection to Databases
- SQL Programming (4): Using the SQL Model Classes
- SQL Programming (5): Presenting Data in a Table View
- SQL Programming (6): Creating Data Aware Forms