QT

QT SQL

2017-05-09  本文已影响0人  托尼章

数据库相关类

类名 描述
QSqlDatabase 代表一个数据库链接
QSqlDriverCreator 为特定的驱动类型提供SQL驱动的模板工厂类
QSqlDriverCreatorBase QSqlDriverCreator的基类
QSqlDriver 用于访问特定SQL数据库的抽象基类
QSqlError SQL 数据库错误信息
QSqlField 操作SQL数据库表和视图中的字段
QSqlIndex 操作和描述数据库索引
QSqlQuery 执行和操作SQL语句
QSqlRecord 封装数据库记录
QSqlResult 用于从特定SQL数据库访问数据的抽象界面
QSql 包含整个Qt SQL模块中使用的标识符
QSqlQueryModel SQL结果集的只读数据模型
QSqlRelationalTableModel 用于单个数据库表的可编辑数据模型,具有外键支持
QSqlTableModel 单个数据库表的可编辑数据模型

数据库相关类分为三个层次:

连接到数据库

在访问数据库之前需要先创建并打开一个或多个数据库链接.数据库链接由链接名称来区分,不由数据库名称区分.同一个数据库上可以有多个数据库链接.
注意创建链接和打开链接的区别:创建链接涉及到QSqlDatabase的实例化.连接在打开之前是不可用的,需要调用open()函数来打开它.

QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName("bigblue");
db.setDatabaseName("flightdb");
db.setUserName("acarlson");
db.setPassword("1uTbSbAs");
bool ok = db.open();

第一句创建链接,最后一句打开链接,中间语句设置链接的各种参数,包括主机名,数据库名,数据库用户名,数据库密码等.第一句中的参数"QMYSQL"指明我们使用MySQL数据库,链接名称为空(默认链接).
如果发生错误请使用QSqlDatabase::lastError()来获取错误信息.
使用QSqlDatabase::database()来获取已经创建的链接.
要删除一个数据库链接,先调用close()再调用removeDatabase().

SQL数据库驱动

Qt SQL模块使用驱动插件来和不同的数据库API进行通讯.因为Qt SQL模块API是"数据库独立的",所有的数据库特异化操作代码都被包含在各自对应的驱动中.Qt SQL模块已经支持一些驱动了,并且你也可以自己添加数据库驱动.下表为已经支持的驱动:

驱动名称 描述
QDB2 IBM DB2 (version 7.1 and above)
QIBASE Borland InterBase
QMYSQL MySQL
QOCI Oracle Call Interface Driver
QODBC Open Database Connectivity (ODBC) - Microsoft SQL Server and other ODBC-compliant databases
QPSQL PostgreSQL (versions 7.3 and above)
QSQLITE2 SQLite version 2
QSQLITE SQLite version 3
QTDS Sybase Adaptive Server Note: obsolete from Qt 4.7

执行SQL语句

QSqlQuery类为执行SQL语句和遍历执行结果集提供了接口.

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

QSqlQuery的构造函数可以接收一个QSqlDatabase对象,以此来指定SQL语句要使用的数据库链接.如果没有提供QSqlDatabase对象,SQL语句会在默认链接上执行.如果有错误exec()函数会返回fasle.使用QSqlQuery::laseError()获取错误信息.

遍历结果集合:

QSqlQuery允许每次访问一条结果集中的记录.调用exec()函数后QSqlQuery的内部指针位于第一个记录的前一个位置,在访问第一条记录之前必须要调用QSqlQuery::next(),依次重复知道next()函数返回值为false.

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

QSqlQuery::value() 返回当前记录中的字段值,返回值是QVariant类型的.
结果集合遍历函数列表:

函数名称 描述
QSqlQuery::next() 下一条记录
QSqlQuery::previous() 上一条记录
QSqlQuery::first() 第一条记录
QSqlQuery::last() 最后一条记录
QSqlQuery::seek() 跳到指定记录
QSqlQuery::at() 当前记录索引
QSqlQuery::size() 总记录条数
QSqlDriver::hasFeature() 当前类型的数据库是否支持某种操作特性
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
{
    query.last();
    numRows = query.at()+1;
}

如果仅使用next()和seek()的正值进行迭代,则可以在调用exec()之前调用QSqlQuery :: setForwardOnly(true). 这是一个简单的优化,可以加快大型结果集上的查询速度。

插入,更新,删除记录

QSqlQuery可执行任意的SQL语句,而不止SELECT语句.

插入示例

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

如果希望插入多条记录,将SQL语句和实际要插入的值分开来写是更高效的,这可以使用占位符来实现,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执行的SQL语句可以通过QSqlQuery::ecutQuery()获取.
插入多条记录时只需要调用一次QSqlQuery::prepare(),然后可以按照你的需要重复多次调用bindValue()或者addBindValue() 和exec().

更新示例

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

同样,更新时也可以使用名称或者位置占位符.

删除示例

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

判断表是否存在

bool isTableExists(QString tableName)
{
      QSqlDatabase db = QSqlDatabase::database();          // 假设数据库连接已经成功打开
      QStringList tableList = db.tables(QSql::AllTables);
      return tableList.contains(tableName);
}

数据库事务

如果底层数据库引擎支持事务,QSqlDriver::hasFeature(QSqlDriver::Transactions)会返回true.调用QSqlDatabase::transaction()来启动事务,后面跟着你想在事务上下文中完成的SQL语句,然后执行QSqlDatabase::commit()或者QSqlDatabase::rollback().使用事务时必须要在创建query前开启事务.

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

事务用于保证复杂的操作的原子性.

使用SQL模型类

除了QSqlQuery之外,Qt提供三个高级类来访问数据库:

类名 描述
QSqlQueryModel 基于任意SQL查询的只读模型
QSqlTableModel 单独一张表上的读写模型
QSqlRelationalTableModel 具有外键支持的QSqlTableModel

这些类继承自QAbstractTableModel(进一步继承自QAbstractItemModel),这使得在诸如QListView和QTableView视图类中呈现数据库中的数据变得简单.

上一篇下一篇

猜你喜欢

热点阅读