目录 前言一、QtSQL简介二、SQLite简介三、QtSQL使用3.1建立数据库连接3.2执行SQL语句3.1.1遍历结果集3.1.2增加、更新和删除记录1.insert2.update3.delete 3.1.3事务操作 3.3SQL 模型类QSqlQueryModelQSqlTableModelQSqlRelationalTableModel 3.4通过视图展示数据创建数据感知表单
前言
因工作需要,要实现一个小型的数据管理系统。本着想捡起来QT技能的想法,学习下QT开发界面管理数据库的操作。
一、QtSQL简介
QtSQL模块实现了对数据库的访问,Qt SQL提供了三个不同层次的API供开发者使用。包括驱动层,SQL API层,用户接口层。
使用该模块需要以下两个步骤:
在项目文件即pro文件中添加如下行 QT += sql 在使用该模块的头文件中添加如下行 #include <QtSql> 二、SQLite简介关系型数据库多种多样,常见的就是甲骨文的ORacle和微软的SQL Server,还有开源的MySQL。这些用在小型数据库管理上有点奢侈和臃肿。 Qt提供了一种进程内数据库SQLite。无需安装,轻量级的。也支持视图、触发器和事务,支持嵌套SQL功能。
三、QtSQL使用 3.1建立数据库连接在进行数据库操作之前,必须首先建立与数据库的连接。数据库通信通常是由连接名称分辨而不是数据库名称。我们可以针对同一个数据库建立多个连接。QSqlDataBase类支持创建默认连接,它是没有名称的。如下是一段创建并打开默认连接的代码
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); db.setHostName("bigblue"); db.setDatabaseName("flightdb"); db.setUserName("acarlson"); db.setPassword("1uTbSbAs"); bool ok = db.open();如上段代码所示,创建数据库连接仅仅是实例化了一个QSqlDatabase类的对象,想要使用它得调用open函数来打开它。静态函数addDatabase原型如下:
QSqlDatabase::addDatabase( const QString &type, const QString &connectionName = QLatin1String(defaultConnection) )参数type为驱动名,可以指定连接到哪些数据库;参数connectionname则为上述的连接名称,如未指定,则使用默认连接名,后续可直接使用不带参数的相关函数。QT支持的驱动如下:
打开数据库连接后我们就可以通过相关函数来操作数据库,在使用完毕后可通过下述两个函数来关闭移除数据库
QSqlDatabase::close() QSqlDatabase::removeDatabase() 3.2执行SQL语句QSqlQuery类提供了一个执行SQL语句的接口并且可以遍历执行的返回结果集。数据库连接建立后就可以使用该类执行底层数据库支持的SQL语句,此方法所要做的仅是创建一个该类实例对象,然后再调用该类的exec()函数。如下:
QSqlQuery query; query.exec("SELECT name, salary FROM employee WHERE salary > 50000"); 3.1.1遍历结果集QSqlQuery类提供了一个获取记录的接口,在调用exec函数后,QSqlQuery类的内部指针指向第一条记录前的位置,我们必须调用一次QSqlQuery::next()函数来获取第一条记录的位置。然后再重复调用next函数,直到返回错误。
while (query.next()) { QString name = query.value(0).toString(); int salary = query.value(1).toInt(); qDebug() << name << salary; }QSqlQuery::value()函数返回当前记录某个属性值。 Fields 是从0开始的索引。 我们可以通过 QSqlQuery::at()获取当前记录的行索引,通过QSqlQuery::size() 获取记录的总数,即行数。 QSqlQuery::value()的返回值是 QVariant类型, 该类型可以转换为多种 C++ and core Qt数据类型,如 int, QString, 和 QByteArray.不同的数据库类型自动映射到相近的Qt类型。
QSQLITE SQLite version 3 Data Types
QSqlQuery可以执行多种SQL语句。不止select,如insert,update,delete。
1.insert QSqlQuery query; query.exec("INSERT INTO employee (id, name, salary) " "VALUES (1001, 'Thad Beaumont', 65000)");插入多个记录可以使用占位符操作,Qt支持两种占位符语法:有名占位和定位占位。分别为 有名占位即Oracle语法
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();定位占位即ODBC语法
QSqlQuery query; query.prepare("INSERT INTO employee (id, name, salary) " "VALUES (?, ?, ?)"); query.addBindValue(1001); query.addBindValue("Thad Beaumont"); query.addBindValue(65000); query.exec(); 2.update QSqlQuery query; query.exec("UPDATE employee SET salary = 70000 WHERE id = 1003"); 3.delete QSqlQuery query; query.exec("DELETE FROM employee WHERE id = 1007"); 3.1.3事务操作事务可以用来确保复杂的操作是原子的(例如,查找外键并创建记录),或者提供一种消除中间复杂变化的方法。 可以使用QSQLDABASE::transaction()启动事务,然后是要在事务上下文中执行的SQL命令,最后是QSQLDABASE::commit()或QSQLDABASE::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(); 3.3SQL 模型类Qt同时也在用户接口层提供了三个模型类来对数据库进行操作,QSqlQueryModel、QSqlTableModel和QSqlRelationalTableModel。这三个类都继承自 QAbstractTableModel ,因此可以很方便的将数据通过QListView和QTableView展示在UI界面内;此外基于模型/视图结构,我们也可以很方便的在不改动代码的情况下更换数据源。
QSqlQueryModel提供了一个基于SQL查询的只读模型
QSqlQueryModel model; model.setQuery("SELECT * FROM employee"); for (int i = 0; i < model.rowCount(); ++i) { int id = model.record(i).value("id").toInt(); QString name = model.record(i).value("name").toString(); qDebug() << id << name; } QSqlTableModel提供了一个基于单张SQL表的可读写模型
QSqlTableModel model; model.setTable("employee"); model.setFilter("salary > 50000"); model.setSort(2, Qt::DescendingOrder); model.select(); for (int i = 0; i < model.rowCount(); ++i) { QString name = model.record(i).value("name").toString(); int salary = model.record(i).value("salary").toInt(); qDebug() << name << salary; }使用该模型,可以替代写SQL语句来操作,如我们可以通过record()来或者表中的一行记录,通过setRecord()修改记录。在模型上的所有修改完成后,使用submitall或者submit来进行提交,更新数据库。
for (int i = 0; i < model.rowCount(); ++i) { QSqlRecord record = model.record(i); double salary = record.value("salary").toInt(); salary *= 1.1; record.setValue("salary", salary); model.setRecord(i, record); } model.submitAll();设置编辑策略 编辑策略表示当用户在视图进行的数据修改是否完全应用到数据库。 取值范围有
基于QSqlTableModel的扩展,支持外键。
3.4通过视图展示数据QSqlQueryModel、QSqlTableModel和QSqlRelationalTableModel类均可以作为数据源在Qt的视图类中表示,如QListView、QTableView和QTreeView等视图类。其中,最常用的是QTableView,因该视图最适合表示二维的SQL操作结果。 如果模型是可读写的,视图将使用户可以编辑字段,我们可以通过如下调用禁止编辑。
view->setEditTriggers(QAbstractItemView::NoEditTriggers);我们可以将一个模型用于多个视图,当在某一视图中更新编辑了模型后,其他视图将随即更新。 使用模型的插入行和删除行操作时,会在视图上进行特殊标注,直到进行提交。 视图类可以显示一个水平表头和一个垂直表头。水平表头在每一列之上显示一个列名,默认情况下,列名就是数据库表的字段名,可以通过setHeaderData()函数修改列名。垂直表头在每一行的最左侧显示本行的行号。
model->setHeaderData(0, Qt::Horizontal, QObject::tr("ID")); model->setHeaderData(1, Qt::Horizontal, QObject::tr("Name")); model->setHeaderData(2, Qt::Horizontal, QObject::tr("City")); model->setHeaderData(3, Qt::Horizontal, QObject::tr("Country")); 创建数据感知表单在某些时候,我们想通过一个表单来获取和更新数据库表中特定行或列的数据,这时候可以使用 QDataWidgetMapper类,具体可参考官方的BOOKS例子。暂时还没用上这个功能。
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。 |