QT学习笔记-QtSQL


前言

因工作需要,要实现一个小型的数据管理系统。本着想捡起来QT技能的想法,学习下QT开发界面管理数据库的操作。


一、QtSQL简介

QtSQL模块实现了对数据库的访问,Qt SQL提供了三个不同层次的API供开发者使用。包括驱动层,SQL API层,用户接口层。

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

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

  1. 在项目文件即pro文件中添加如下行
QT += sql 
  1. 在使用该模块的头文件中添加如下行
#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 nameDBMS
QDB2IBM DB2 (version 7.1 and above)
QIBASEBorland InterBase
QMYSQLMySQL
QOCIOracle Call Interface Driver
QODBCOpen Database Connectivity (ODBC) - Microsoft SQL Server and other ODBC-compliant databases
QPSQLPostgreSQL (versions 7.3 and above)
QSQLITE2SQLite version 2
QSQLITESQLite 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.NULL
INTEGERSigned integer, stored in 8, 16, 24, 32, 48, or 64-bits depending on the magnitude of the value.typedef qint8/16/32/64
REAL64-bit floating point value.By default mapping to QString
TEXTCharacter string (UTF-8, UTF-16BE or UTF-16-LE).Mapped to QString
CLOBCharacter large string objectMapped to QString
BLOBThe 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例子。暂时还没用上这个功能。

  • 8
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt SQL中,可以使用QSqlQuery来执行数据库删除操作。具体的删除语句可以通过qry.exec()方法传入一个字符串,包含要执行的SQL语句。例如,可以使用以下代码删除名为"Sys_user"表中满足给定条件的记录: QSqlQuery qry(db); qry.exec(QString("delete from Sys_user where name = '%1' and password = '%2';").arg(res1).arg(res2)); 这段代码中,res1和res2是要匹配的条件值。同样的方式也可以用来删除其他表中的记录,只需修改表名和条件。 另外,当执行数据库删除操作后,已删除的记录所占用的内存并不会自动释放,而是保留为碎片。为了释放这些碎片空间,可以使用vacuum功能。例如,可以像以下代码一样在删除操作后执行vacuum: QSqlQuery qry(db); qry.exec("vacuum"); 执行vacuum操作后,被删除记录所占用的内存碎片将被释放,数据库文件的大小也会相应变小。 总结起来,Qt SQL中的删除操作可以通过QSqlQuery的exec()方法执行SQL语句来实现,同时可以使用vacuum功能释放删除操作所占用的内存碎片。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [qtsql删除间隔大量数据](https://blog.csdn.net/qq_37603131/article/details/104131769)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [QtCreator Qt中执行SQL语句,select,update,delete,insert](https://blog.csdn.net/psujtfc/article/details/38057421)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值