irpas技术客

QT学习笔记-QtSQL_Q-Stark_qtsql

大大的周 6628

目录 前言一、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层,用户接口层。

层次描述驱动层实现了特定数据库与SQL接口的底层桥接,包括的支持类有QSqlDriver、QSqlDriverCreator、QSqlDriverCreatorBase、QSqlDriverPlugin和QSqlResultSQL API层QSqlDataBase类提供了数据库访问接口、数据库连接操作;QSqlQuery类提供了与数据库交互的操作,其他支持类还包括QSqlError、QSqlField、QSqlTableModel和QSqlRecord用户接口层提供从数据库数据到用于数据表示的窗体的映射,包括的支持类有QSqlQueryModel、QSqlTableModel和QSqlRelationalTableModel,这些类均依据Qt的模型/视图结构设计

使用该模块需要以下两个步骤:

在项目文件即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支持的驱动如下:

Driver nameDBMSQDB2IBM DB2 (version 7.1 and above)QIBASEBorland InterBaseQMYSQLMySQLQOCIOracle Call Interface DriverQODBCOpen Database Connectivity (ODBC) - Microsoft SQL Server and other ODBC-compliant databasesQPSQLPostgreSQL (versions 7.3 and above)QSQLITE2SQLite version 2QSQLITESQLite version 3

打开数据库连接后我们就可以通过相关函数来操作数据库,在使用完毕后可通过下述两个函数来关闭移除数据库

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

QSQLITE SQLite version 3 data typeSQL type descriptionRecommended input (C++ or Qt data type)NULLNULL value.NULLINTEGERSigned integer, stored in 8, 16, 24, 32, 48, or 64-bits depending on the magnitude of the value.typedef qint8/16/32/64REAL64-bit floating point value.By default mapping to QStringTEXTCharacter string (UTF-8, UTF-16BE or UTF-16-LE).Mapped to QStringCLOBCharacter large string objectMapped to QStringBLOBThe value is a BLOB of data, stored exactly as it was input.Mapped to QByteArray
3.1.2增加、更新和删除记录

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::OnFieldChange0所有对模型的更改都会立即在数据库内更新QSqlTableModel::OnRowChange1当前行的修改在用户选择另一不同行时生效QSqlTableModel::OnManualSubmit2所有修改暂存在模型中,直到调用submitAll()或者revertAll()
model->setEditStrategy(QSqlTableModel::OnManualSubmit); QSqlRelationalTableModel

基于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.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #qtsql #一QtS