声明:不知为何,从EverNote复制过来的文章在开源中国的博客编辑器无法显示图片,完整版已转到ChinaUnix,请原谅。地址:http://blog.chinaunix.net/uid-29650836-id-4555470.html
简介:
Qt SQL 是 Qt 的重要模块之一,为了方便,Qt 对 SQL 进行了一系列的封装,并将 SQL API 分为如下三层:
(1)驱动层
(2)SQL API 层
(3)用户接口层
目录:
一、使用前提
二、数据库类
三、连接到数据库
· SQL 数据库驱动
四、执行 SQL 语句
· Qt 支持的数据库系统的数据类型
五、使用 SQL Model 类
一、使用前提:
(1)在C++文件中加入相应头文件
#include <QtSql>
(2)在Qt 工程文件中加入Qt SQL 模块
QT += sql
二、数据库类
(1)驱动层
驱动层包含如下几个类:
QSqlDriver, QSqlDriverCreator, QSqlDriverCreatorBase, QSqlDriverPlugin, and QSqlResult.
驱动层在特定的数据库系统和SQL API之间架设了一个底层的桥梁,这使得其是数据库无关的,也就是说,Qt将各种不同的数据库当作一个对象,而使用它们的方法则是通过驱动插件将其载入程序当中。我们可以这样理解:只要Qt版本的驱动程序支持,该数据库就是可用的。如图是Qt支持的数据库类型:
(2)SQL API 层
这个类的集合的主要功能是访问数据库,言外之意就是对数据库进行各种操作的方法类的集合。例如可以通过
QSqlDatabase建立连接,通过
QSqlQuery进行数据库交互(查询等)。此外,还包括几个常用类:
QSqlError, QSqlField, QSqlIndex, and QSqlRecord.
(3)用户接口层
用户接口层的类包括:
QSqlQueryModel, QSqlTableModel, and QSqlRelationalTableModel.
它们可用于将数据投射到具体的部件上,当然该部件必须具备Qt的模型与视图
model/view框架。
注意:在使用Qt Sql 类之前,必须将QCoreApplication对象实例化。
三、连接到数据库
通过
QSqlQuery和
QSqlQueryModel访问数据库将创建一个或多个数据库连接。数据库连接用数据库连接名称
[ConnectionName]来区别,而非数据库名称
[DatabaseName]。对同一数库可以有多个连接。此外,
QSqlDatabase也支持默认连接的概念,当然这个默认连接是未命名的。当调用
QSqlQuery或
QSqlQueryModel的带连接名参数的成员函数时,如果不传递连接名,将使用默认连接。
请注意创建连接和打开连接是有差别的。创建连接将创建一个
QSqlDatabase对象,而在打开此连接之前,该连接是不可用的。
Qt官方举了一个例子:
第一行创建了一个默认的数据库连接,因为该程序中并未将具体的连接名作为第二个参数传递给addDatabase(),可以这样修改:
"
这样就创建了名为
"first"和
"second两个连接。值得一提的是,在打开连接之前,需要对连接进行初始化操作,包括:
setHostName()、setDatabaseName()、setUserName()和setPassword()。连接初始化之后,就可以调用
open()打开,如果打开失败,将返回
false,通过调用
lastError()可以获得错误信息。另外,连接建立之后,调用
database()将返回连接名,移除连接之前先调用
c
lose()关闭之,然后再调用
removeDatabase()移除。
四、执行SQL语句
执行查询
QSqlQuery类提供执行SQL语句和查询的接口,而
QSqlQueryModel和
QSqlTableModel则提供数据库操作的高级接口。
执行一条SQL语句之前,需要创建一个
QSqlQuery对象,之后再调用
QSqlQuery::exec(),例如:
QSqlQeury构造器允许接收一个可选的
QSqlDataBase对象,该对象必须是数据库连接所使用的,上例中没有传递数据库连接对象,因此将采用默认的数据库连接。
操作结果集
QSqlQuery同样提供对结果集的访问,在调用
exec()之后,
QSqlQuery的内部指针将指向结果集中的第一条记录之前,通过调用
next()可以取得第一条记录,之后再调用next()就可以取得下一条记录。如下例,其效果相当于遍历结果集:
QSqlQeury::value()返回当前记录的指定字段值,其返回值类型是
QVariant,
QVariant实际上是一种联合体类型,因此需要将其转换成需要的格式(
int/QString/QByteArray等)。
我们也可以把
QSqlQuery当作一个迭代器来看,因为它支持
QSqlQuery::next(), QSqlQuery::previous(), QSqlQuery::first(), QSqlQuery::last(), and QSqlQuery::seek().QSqlQuery::at()返回当前记录的行索引,
QSqlQuery::size()返回结果集的记录条数,但前提是
QSqlQuery::size() 要求对应数据库驱动的支持。
插入,更新和删除
QSqlQuery可以执行任意的SQL语句,并非仅限于
SELECTS。如插入记录:
如果你想在同一时间插入多个记录,可以使用
binding来做:
更新记录或称修改记录,类似于插入记录:
最后,删除记录:
事务处理
如果底层数据库引擎支持事务处理,那么
QSqlDriver::hasFeature(QSqlDriver::Transactions)会返回true。通过调用
QSqlDatabase::transactions()可以初始化一个事务,之后就可以进行执行SQL语句的操作,或者调用
QSqlDatabase::commit()或者
QSqlDatabase::rollback()了。
值得注意的是:在使用事务处理的时候,必须在创建query之前启动事务transaction。如下:
事务处理可用于数据的保护,因为其操作是原子的(例如查询外键和创建记录),且提供一套回滚机制。
五、使用 SQL Model 类
除了
QSqlQuery,Qt还提供了三种更高级的类以访问数据库,它们是
QSqlQueryModel, QSqlTableModel, and QSqlRelationalTableModel.
这些类派生于
QAbstractTableModel,且使得数据库中的数据可以方便在视图类中显示,例如
QListView和
QTableView。
The SQL Query Model
QSqlQueryModel提供一个基于SQL query的只读模型。示例如下:
使用
QSqlQeuryModel::setQuery()设置query之后,可以使用
QSqlQueryModel::record(int)来访问单独的记录,或者调用
QSqlQueryModel::data()或者其他继承自
QAbstractItemModel的方法。
The SQL Table Model
QSqlTableModel提供一个基于简单SQL表格的可读可写的模型。如下例:
QSQlTableModel是QSqlQuery的高级替代方案,它可用于浏览和修改单个SQL表,而且,它也并不需要用户熟悉SQL的语法。
使用QSqlTableModel::record()可以检索表中的一行记录,QSqlTableModel::setRecord()用于修改行记录。如下例所示:
当然,也可以使用QSqlTableModel::data() and QSqlTableModel::setData()来访问数据库。如下例所示:
setData():
插入一条记录:
删除五条连续的记录:
当记录改变之后,必须调用QSqlTableModel::submitAll()提交保存,否则数据是不写入的。何时又是否调用QSqlTableModel::submitAll()取决于表格的edit strategy(编辑策略),默认的编辑策略是 QSqlTableModel::OnRowChange(随行变化),其他的策略如下所示:
The SQL Relational Table Model
QSqlRelationalTableModel 扩展了
QSqlTableModel 以提供对外键的支持。外键是一张表中的一个字段和另一张表中的主键字段之间的一对一的映射。
表1是使用
QSqlTableModel展现在
QTableView中的一张表格,外键city和country还没有解析为可读的数值。表2采用了
QSqlRelationalTableModel来展示,其外键已经转换为可读的字符串数值。下列代码片段展示了
QSqlRelationalTableModel的建立过程:
PS:
这篇文章翻译于Qt的SQL模块,中间有删减,另外加了一些个人的理解。
整篇Qt SQL Programming并未完全翻译出来,之后还有Qt的两个例子,大家可以自己去看看。
由于英文功底有限,翻译中可能存在多个不当之处,望不吝指出,共同进步。