Qt中SQLite数据库的使用

embedded/2024/9/25 8:33:16/

一、安装SQLite

        在Qt6中,不再支持 SQLite2,只支持 SQLite3 。因此,有两种方式使用 SQLite,一种是在 SQLite 官网安装 SQLite3,另外一种是直接安装 SQLite Expert。

        SQLite Expert 内置了 SQLite。这意味着用户在安装 SQLite Expert 后,无需单独安装 SQLite 即可使用其全部功能。内置的 SQLite 引擎使得用户能够直接创建、管理和操作 SQLite 数据库,而不必担心额外的配置和兼容性问题。点击如下链接即可安装:

SQLite administration | SQLite Expert

二、连接SQL

1. 修改项目配置文件(.pro文件)

        如果需要在Qt项目中使用数据库编程功能,需要将Qt SQL模块添加到项目中,也就是需要在项目配置文件中增加下面一句:

QT += sql

 2. 修改头文件(.h文件)

        如果要使用一些常用的Qt SQL类,在头文件中则需要添加如下代码:

#include <QtSql>

3. 添加数据库连接(.cpp文件)

        QSqlDatabase 类用于建立与数据库的连接,而 QSqlDatabase 对象就表示这种连接。例如接下来说的 QSqlQuerryModel 模型类查询数据库时,就必须设置它。它的函数原型定义如下:

QSqlDatabase QSqlDatabase::addDatabase(const QString &type, const QString &connectionName = QLatinString(defaultConnection))
  •  type:连接的数据库类型;
  • connectionName:所创建的数据库连接名称,若不设置则使用默认的数据库连接名称"qt_default_connection"

举个例子: 

//打开数据库
void MainWindow::on_actOpenDB_triggered()
{QString aFile = QFileDialog::getOpenFileName(this,"选择文件","","SQLite数据库(*.db3)");if (aFile.isEmpty())return;QSqlDatabase DB = QSqlDatabase::addDatabase("QSQLITE");  //添加 SQLITE数据库驱动DB.setDatabaseName(aFile);   //设置数据库文件if (DB.open())       //成功打开数据库selectData();  // 展示数据库数据elseQMessageBox::warning(this, "错误", "打开数据库失败");
}

         这段代码中,当在打开的文件对话框中选中一个 .db3 文件并打开后,就成功地创建了一个SQLite数据库连接。

三、关于Qt SQL的模型类

        了解这些内容之前,我们必须知道各个模型类的继承关系。

1. QSqlQuerryModel

        这是一个表示SQL查询结果数据的模型类,它通过设置select语句查询数据库的数据。因此,这个模型类的数据是只读的,不可修改

        要想将数据库中查询到的数据作为 QSqlQuerryModel 的数据源,就必须使用 setQuery() 函数,其函数定义如下:

void QSqlQueryModel::setQuery(const QString &query, const QSqlDatabase &db = QSqlDatabase())
  • query:一条完整的select语句,用来查询数据库
  • db:数据库连接 ,若不指定,则使用程序默认数据库连接

举个例子: 

//查询数据
void MainWindow::selectData()
{QSqlQueryModel qryModel = new QSqlQueryModel(this);qryModel->setQuery("SELECT empNo, Name, Gender,  Birthday,  Province,  Department, Salary FROM employee ORDER BY empNo", DB);ui->tableView->setModel(qryModel);
}

         这样在视图中就可通过 QSqlQuerryModel 模型显示数据库中的数据。

2. QSqlTableModel

        表示单个数据表的模型类。直接设置一个数据表的名称,就可以获取数据表的全部记录。与QSqlQuerryModel 不同的是,它的数据是可编辑的。其函数定义如下:

QSqlTableModel (QObject *parent = nullptr, const QSqlDatabase &db = QSqlDatabase())

举个例子:

// 打开数据表
void MainWindow::openTable()
{QSqlTableModel tabModel = new QSqlTableModel(this, DB);	tabModel->setTable("employee");			//选择一个数据表作为数据源tabModel->setEditStrategy(QSqlTableModel::OnManualSubmit);	 //设置为临时保存策略if (!(tabModel->select())) {	//查询数据失败QMessageBox::critical(this, "错误信息", "打开数据表错误,错误信息:\n" + tabModel->lastError().text());return;}ui->tableView->setModel(tabModel);
}// 保存修改
void MainWindow::on_actSubmit_triggered()
{tabModel->submitAll();
}// 取消修改
void MainWindow::on_actRevert_triggered()
{tabModel->revertAll();
}

        与 QSqlQuerryModel 不同的是,我们无须使用select语句直接使用内置的 select() 方法即可。而且当在tableView视图中修改了某项数据后,可以通过 submitAll() 将数据的修改提交到数据库

3. QSqlRelationalTableModel

        它可以作为具有编码字段的数据表的模型类。这是什么意思?

        如上面三张表,我们希望将第一张表的 majorID 字段与第二章表的 majorID 字段连接,然后将第一张表的majorID“编码”为第二张表的major。同理第三张表也是如此。

        那么这种操作就需要用到 QSqlRelationalTableModel ,其函数定义如下:

QSqlRelationalTableModel (QObject *parent = nullptr, const QSqlDatabase &db = QSqlDatabase())

        如何设置上述的SQL的外键关系?主要用到一个函数 setRelation() :

void QSqlRelationalTableModel::setRelation(int column, const QSqlRelation &relation)
QSqlRelation(const QString &tableName, const QString &indexColumn, const QString &displayColumn)
  • column:外键字段的字段序号;
  • relation:一个 QSqlRelation 对象
    • tableName:编码表表名
    • indexColumn:外键字段名
    • displayColumn:编码表中代码含义字段名称

 举个例子:

// 打开数据表
void MainWindow::openTable()
{QSqlRelationalTableModel tabModel = new QSqlRelationalTableModel(this, DB);tabModel->setTable("studInfo");     tabModel->setEditStrategy(QSqlTableModel::OnManualSubmit); ui->tableView->setModel(tabModel);//设置外键关系--QSqlRelation("另一个表名","另一个表里的外键","另一个表里的字段名称"))tabModel->setRelation(tabModel->fieldIndex("departID"), QSqlRelation("departments","departID","department"));  //学院tabModel->setRelation(tabModel->fieldIndex("majorID"), QSqlRelation("majors","majorID","major"));            //专业//为关系型字段设置默认代理组件ui->tableView->setItemDelegate(new QSqlRelationalDelegate(ui->tableView));  
}

        这样,当我们用tableView显示上述数据库表一内容时,就会自动编码majorID和departID。而且QSqlRelationalTableModel的默认代理组件也会对单元格进行委托代理,实现类似QComboBox样式的编辑效果。

四、QSqlQuery类

         在上述的模型类当中,我们只能双击单元格修改、再点击提交的方式修改数据库中的数据。这样显得很呆!而 QSqlQuery 是能运行任何 SQL 语句的类,如select、insert、update、delete等常用SQL语句。

        但是,QSqlQuery 并没有父类,与上述模型类没有直接继承关系,因此查询到的数据并不能作为 模型/视图 结构中的数据模型,只能作为一个数据集使用。

        几个重要的接口函数如下:

bool prepare()     //设置准备运行的SQL语句
void bindValue()     // 绑定prepare()中的SQL语句含有的参数
void exec()     //运行设置好的SQL语句
QString executedQuery()     //返回上一次成功执行的SQL语句

        注:若 prepare() 函数中没有参数,可以直接在 exec()  函数中放置SQL语句直接执行。

        举个例子:

// tableView上双击,编辑当前记录
void MainWindow::on_tableView_doubleClicked(const QModelIndex &index)
{int curRecNo = index.row();updateRecord(curRecNo);
}// 更新一条记录
void MainWindow::updateRecord(int recNo)
{QSqlRecord curRec = qryModel->record(recNo);  //获取数据模型的一条记录int empNo = curRec.value("EmpNo").toInt();    //获取员工工号这个主键QSqlQuery query;query.prepare("select * from employee where EmpNo = :ID");query.bindValue(":ID",empNo);query.exec();if (!query.isValid())return;TDialogData *dataDialog = new TDialogData(this); //创建对话框if (dataDialog->exec() == QDialog::Accepted){QSqlRecord recData = dataDialog->getRecordData();    //获得对话框返回的记录query.prepare("update employee set Name=:Name, Gender=:Gender,"" Birthday=:Birthday,  Province=:Province,"" Department=:Department, Salary=:Salary,"" Memo=:Memo, Photo=:Photo "" where EmpNo = :ID");query.bindValue(":Name", recData.value("Name"));query.bindValue(":Gender", recData.value("Gender"));query.bindValue(":Birthday", recData.value("Birthday"));query.bindValue(":Province", recData.value("Province"));query.bindValue(":Department", recData.value("Department"));query.bindValue(":Salary", recData.value("Salary"));query.bindValue(":Memo", recData.value("Memo"));query.bindValue(":Photo", recData.value("Photo"));query.bindValue(":ID", empNo);if (!query.exec())QMessageBox::critical(this, "错误", "记录更新错误\n" + query.lastError().text());else//数据模型重新查询数据,更新tableView显示qryModel->setQuery(qryModel->query().executedQuery());}delete dataDialog;      //删除对话框
}

        注意:在重新查询数据时,下列写法是错误的: 

//query.executedQuery()返回上一条成功执行的SQL语句
qryModel->setQuery(query.executedQuery());

        因为query对象为QSqlQuery类,它的上一条成功执行的SQL语句不一定是select子句。而qryModel对象为QSqlQueryModel类,它只能执行select子句,否则会导致编译错误。

        当我们再次双击单元格想要修改某一项数据时,就会打开一个 “更新记录” 的对话框。对话框将获取到的信息作为 bindValue() 函数的参数,最后用 exec() 执行后,数据库中的数据就会改变。当然,想要界面上的信息也发生改变,数据模型必须重新查询数据库中的数据。


http://www.ppmy.cn/embedded/92696.html

相关文章

未来已来:人工智能如何重塑Facebook的用户体验?

在数字化时代的浪潮中&#xff0c;人工智能&#xff08;AI&#xff09;正成为推动技术进步和用户体验优化的核心力量。Facebook&#xff08;现Meta Platforms&#xff09;作为全球领先的社交媒体平台&#xff0c;正在充分利用人工智能技术&#xff0c;以重塑用户体验&#xff0…

【C语言】预处理详解(下)

文章目录 前言6. 宏和函数的对比7. #和##7.1 #运算符7.2 ##运算符&#xff08;运用较少&#xff0c;了解即可&#xff09; 8. 命名的约定9. #undef &#xff08;了解即可&#xff09;10. 条件编译&#xff08;重点&#xff09;11. 头文件的包含11.1 头文件被包含的方式&#xf…

【nginx】解决k8s中部署nginx转发不会自动更新域名解析启动失败的问题

文章目录 1. 问题2.解决办法3.扩展说明3.1 DNS解析阶段划分3.2 问题说明3.2.1 先看/etc/resolv.conf说明3.2.2 针对第一个问题3.2.3 针对第二个问题 【后端】NginxluaOpenResty高性能实践 参考&#xff1a; https://blog.csdn.net/u010837612/article/details/123275026 1. 问…

SpringBoot自动装配原理

SpringBoot自动装配原理 SpringBootApplication 中包含了三个核心注解 SpringBootConfiguration 声明当前的类是配置类 ComponentScan 组件扫描,默认扫描引导类所在包以及子包 EnableAutoConfiguration 实现SpringBoot自动化配置的核心注解 EnableAutoConfiguration …

24.8.5数据结构|栈

栈-弹夹 1、定义&#xff1a; 栈就是特殊的线性表&#xff0c;与之前的线性表的区别就是增加了约束&#xff0c;只允许在一端插入和删除&#xff0c;就这麽简单。 2、基本操作 栈的插入操作叫&#xff1a;入栈{进栈、压栈}&#xff1b;栈的删除&#xff1a;出栈{退栈&#x…

BitNet——用单个比特进行推理的大语言模型,性能媲美全精度Transformer

概述 为了实现高精确度&#xff0c;大规模语言模型变得越来越大&#xff0c;但随着模型越来越大&#xff0c;其部署也面临挑战&#xff0c;人们担心计算量和能耗会增加。本研究提出了权重为 1 的单比特变换器&#xff0c;结果表明它能以更少的计算资源和更高的能效实现与传统 …

大数据信用报告查询有什么作用?怎么选择查询平台?

随着互联网的快速发展&#xff0c;人们的金融行为越来越多地依赖于网络平台。然而&#xff0c;网络上的金融交易存在着一定的风险&#xff0c;为了有效地防范这些风险&#xff0c;金融机构采用了大数据技术进行风险控制&#xff0c;下面&#xff0c;小易大数据平台将详细介绍大…

【滴水三期】32/64位——PE文件头字段打印与解析

一、【作业描述】 1、编写程序读取一个exe文件&#xff0c;输出所有的PE头信息&#xff1b; 2、使用第三方的PE工具&#xff0c;对比如下信息&#xff0c;看是否一致&#xff1b; 二、【PE头字段解析】 注&#xff1a;海哥发的PE结构 PDF也不是特别全的&#xff0c;可以去&…