当前位置: 首页 > news >正文

QT-数据库编程

数据库编程

采用SQLite数据库进行应用开发,SQLite数据库是一种单机(本地)数据库, 不支持远程连接,是一种文件数据库,所有的表、索引等数据库元素全部存储在一个文件里。

官网下载SQLite数据库

官网下载地址:https://www.sqlite.org/download.html

根据你的操作系统(这里是Windows)和架构(32位或64位),找到合适的下载文件。

  • sqlite-dll-win32-x86-xxxxxx.zipsqlite-dll-win64-x64-xxxxxx.zip (动态链接库文件,用于在应用程序中链接SQLite)
  • sqlite-tools-win32-x86-xxxxxx.zipsqlite-tools-win64-x64-xxxxxx.zip (包含命令行工具如sqlite3.exe,用于直接操作数据库)

如图:

在这里插入图片描述

下载并解压以上文件到同一个目录下,例如 D:\sqlite3

在此目录-打开命令窗口,输入sqlite3,返回版本信息等内容,说明安装成功

使用SQLite3命令行工具创建数据库

在命令行中输入 sqlite3 后跟数据库文件名:

sqlite3 mydatabase.db

一旦数据库被创建,可以使用 SQLite 的 .databases 命令来检查它是否在数据库列表中,如下所示:

sqlite>.databases

使用 SQLite .quit 命令退出 sqlite 提示符,如下所示:

sqlite>.quit

执行SQL命令

一旦进入SQLite提示符,就可以执行SQL命令来创建表和执行其他数据库操作:

CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT);
INSERT INTO users (name) VALUES ('hello');SELECT * FROM users;

可视化工具

SQLite Expert是SQLite数据库的可视化管理工具,SQLite Expert安装文件中带有SQLite数据库驱动。使用SQLite Expert可以创建和管理数据库,一个数据库就是一个.db3的文件。

一、Qt SQL模块

Qt SQL模块提供了一个与平台及数据库无关的访问数据库的接口。

Qt SQL模块中主要的类:

在这里插入图片描述

如果要使用Qt SQL模块中的类,就需要再项目文件(.pro文件)中添加QT += sql代码配置。

二、访问数据库

Qt中访问数据库的步骤如下:

在这里插入图片描述

1、创建QSqlDatabase对象

通过添加数据库驱动,并指定使用的驱动类型(如MySQL、PostgreSQL、SQLite等数据库的驱动),建立应用程序与特定数据库之间的连接,从而能够使用Qt的SQL模块API与数据库进行交互。

添加驱动并创建QSqlDatabase对象:

QSqlDatabase database = QSqlDatabase::addDatabase("QSQLITE");
2、设置数据库名称

指定要访问的数据库的名称。如果本目录下没有该文件,则会创建,否则连接该文件。

database.setDatabaseName("数据库名");
3、打开数据库

如果成功返回true,失败返回false。

database.open();

可以用QSqlError::driverText()得到错误信息。database.lastError()会返回QSqlError对象。

bool result = datebase.open();
if (result)
{        qDebug() << "数据库连接成功";
}
else
{QSqlError lastError = database.lastError();qDebug << lastError.driverText();
}
4、执行查询等操作

通过QSqlQuery对象执行sql语句。

QSqlQuery query("select * from student");
query.exec();
5、处理结果
while (query.next()) {  //定位到第一行记录qDebug() <<  query.value("id").toInt()  //根据列名查询对应数据<< query.value("name").toString() << query.value("age").toInt();
}
6、清除结果集、关闭数据库

清理 QSqlQuery 对象。每次执行完SQL查询操作后,QSqlQuery 对象都会持有查询结果集。调用 clear() 方法可以清空查询结果集,并释放与此查询相关的内存资源。

关闭 器的连接。当应用程序完成数据库操作后,及时关闭数据库连接可以释放系统资源。

query.clear();
database.close();
7、示例代码

(1)查询示例

#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>void testDatabase()
{// 1. 连接 SQLite 数据库(驱动是 QSQLITE)QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");db.setDatabaseName("d:/sqllitedb/test.db3");// 2. 打开数据库if (!db.open()) {qDebug() << "数据库打开失败:" << db.lastError().text();return;}// 3. 执行 SQL 查询QSqlQuery query;if (!query.exec("SELECT empno, ename, salary FROM employee")) {qDebug() << "查询失败:" << query.lastError().text();return;}// 4. 遍历查询结果while (query.next()) {QString empno  = query.value(0).toString();  // 第一列QString ename  = query.value("ename").toString();  // 也可以用列名QString salary = query.value(2).toString();  // 第三列qDebug() << empno << ename << salary;}// 5. 关闭数据库db.close();
}

(2)添加、删除、修改数据

#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>// 打开数据库
QSqlDatabase open()
{QSqlDatabase database = QSqlDatabase::addDatabase("QSQLITE");   // 添加 SQLite 数据库驱动database.setDatabaseName("d:/sqllitedb/test.db3");              // 指定数据库文件路径database.open();                                                // 打开数据库return database;                                                // 返回数据库对象
}void insert()
{QSqlDatabase database = open();                                 // 打开数据库QSqlQuery query;                                                // 执行 SQL 语句的对象query.prepare("INSERT INTO employee (name, age) VALUES (?, ?)"); // 使用 ? 占位符预处理 SQLquery.addBindValue("John Doe");                                 // 绑定第一个参数:namequery.addBindValue(30);                                         // 绑定第二个参数:agebool result = query.exec();                                     // 执行 SQLif (!result)                                                    // 如果失败{QSqlError lastError = database.lastError();                 // 获取最后的错误信息qDebug() << lastError.driverText();                         // 输出错误原因}database.close();                                               // 关闭数据库
}void update()
{QSqlDatabase database = open();                                 // 打开数据库QSqlQuery query;                                                // 执行 SQL 的对象query.prepare("update employee set salary = ? where empno = ?");// 更新语句,两个参数query.addBindValue("John Doe");                                 // 错误演示:这里本应是工资值query.addBindValue(1);                                          // 员工编号为 1bool result = query.exec();                                     // 执行 SQLif (!result){QSqlError lastError = database.lastError();                 // 获取错误信息qDebug() << lastError.driverText();                         // 打印错误}database.close();                                               // 关闭数据库
}void del()
{QSqlDatabase database = open();                                 // 打开数据库QSqlQuery query;                                                // SQL 执行对象query.prepare("delete from employee where empno = ?");          // 删除语句query.addBindValue(1);                                          // 删除 empno = 1 的记录bool result = query.exec();                                     // 执行 SQLif (!result){QSqlError lastError = database.lastError();                 // 获取错误信息qDebug() << lastError.driverText();                         // 打印错误}database.close();                                               // 关闭数据库
}

三、QSqlTableModel

在 Qt 中进行数据库编程时,通常会使用模型/视图(Model/View)架构来处理数据和用户界面之间的交互。模型负责管理数据以及数据相关的操作。

对于数据库应用来说,最常用的模型包括:

  • QSqlTableModel:适用于表格式的数据,它直接从数据库表读取数据并提供给视图。
  • QSqlQueryModel:适用于执行 SQL 查询返回的结果集,它可以灵活地展示任意查询结果。

QSqlTableModel模型类通常和QTableView组件构成模型/视图结构,实现数据表的数据显示和编辑。

完成如下项目:

在这里插入图片描述

1、打开数据库
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QSqlDatabase>       // 数据库类
#include <QSqlTableModel>     // 表格模型类QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;             // 前向声明 UI 类
}
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr); // 构造函数~MainWindow();                         // 析构函数private slots:void on_actionOpenDB_triggered();      // 菜单动作:打开数据库private:Ui::MainWindow *ui;                    // UI 指针QSqlDatabase database;                 // 数据库连接对象QSqlTableModel *model;                 // 数据表模型(用于显示数据)void openTable();                      // 打开并加载表格的方法
};#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>     // 文件选择对话框
#include <QMessageBox>     // 消息提示框
#include <QSqlError>       // 数据库错误信息类MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)   // 构造函数,继承 QMainWindow, ui(new Ui::MainWindow) // 初始化 UI
{ui->setupUi(this);      // 设置 UI
}MainWindow::~MainWindow()
{delete ui;              // 释放 UI 内存
}void MainWindow::on_actionOpenDB_triggered()
{QString filename = QFileDialog::getOpenFileName(this, "选择文件","","数据库(*.db)"); // 打开文件选择对话框,选择数据库文件if (filename.isEmpty()) // 如果没有选择文件{return;             // 直接返回}database = QSqlDatabase::addDatabase("QSQLITE"); // 添加 SQLite 数据库驱动database.setDatabaseName(filename);              // 设置数据库文件名if (!database.open())   // 尝试打开数据库{QSqlError error = database.lastError();        // 获取错误信息qDebug() << error.text();                    // 在控制台打印错误QMessageBox::warning(this, "错误", "打开数据库失败"); // 弹出警告提示}else{openTable();        // 如果数据库打开成功,调用 openTable() 打开表}
}void MainWindow::openTable()
{model = new QSqlTableModel(this, database); // 创建数据表模型,绑定到 databasemodel->setTable("employee");               // 设置模型对应的表为 "employee"model->setEditStrategy(QSqlTableModel::OnManualSubmit); // 设置编辑策略:手动提交model->setSort(model->fieldIndex("empno"), Qt::AscendingOrder); // 按 empno 升序排序if (!model->select())  // 执行查询,如果失败{QMessageBox::critical(this, "打开数据表失败", "错误信息:\n" + model->lastError().text()); // 弹出错误提示框return;}
}
2、设置表头
//初始化视图数据
void MainWindow::initData()
{//设置表头数据//orientation:表示要设置的是水平(Qt::Horizontal,即列头)还是垂直(Qt::Vertical,即行头)的表头数据。model->setHeaderData(model->fieldIndex("empno"), Qt::Horizontal, "工号");model->setHeaderData(model->fieldIndex("ename"), Qt::Horizontal, "姓名");model->setHeaderData(model->fieldIndex("gender"), Qt::Horizontal, "性别");model->setHeaderData(model->fieldIndex("birthday"), Qt::Horizontal, "出生日期");model->setHeaderData(model->fieldIndex("province"), Qt::Horizontal, "省份");model->setHeaderData(model->fieldIndex("department"), Qt::Horizontal, "部门");model->setHeaderData(model->fieldIndex("salary"), Qt::Horizontal, "薪水");model->setHeaderData(model->fieldIndex("memo"), Qt::Horizontal, "备注");//设置隐藏列ui->tableView->hideColumn(model->fieldIndex("remark"));
}
3、添加记录
model->setEditStrategy(QSqlTableModel::OnManualSubmit); //添加功能需要改成手动提交
void MainWindow::on_actionAdd_triggered()
{QSqlRecord record = model->record();//获取一条空记录,只有字段定义model->insertRecord(model->rowCount(), record);selection->clearSelection();QModelIndex index = model->index(model->rowCount()-1, 0);selection->setCurrentIndex(index, QItemSelectionModel::Select);//设置选择行
}
4、删除记录
void MainWindow::on_actionDelete_triggered()
{int ok = QMessageBox::warning(this, "删除记录", "确定删除?", QMessageBox::Ok | QMessageBox::Cancel);if (ok == QMessageBox::Ok){QModelIndex index = selection->currentIndex();model->removeRow(index.row());bool result = model->submitAll();if (result){QMessageBox::information(this, "", "删除成功");}else{QMessageBox::information(this, "", "删除失败");}}
}

设置选择模式:

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);//设置选择模式。表格视图这里采用单选模式,在同一时间只能有一个单元格或一行被选中。ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);ui->tableView->setAlternatingRowColors(true); //交错行变色
}
5、保存/取消
void MainWindow::on_actionSave_triggered()
{bool result = model->submitAll();if (result){QMessageBox::information(this, "保存数据", "保存成功");}else{QMessageBox::information(this, "保存数据", "保存失败");}
}
void MainWindow::on_actionReverse_triggered()
{model->revertAll();
}
6、撤销
void MainWindow::on_action_6_triggered()
{model->revertAll();
}
10、记录排序
void MainWindow::on_radioButtonAsc_clicked()
{model->setSort(ui->comboBoxSort->currentIndex(), Qt::AscendingOrder); // 设置排序:根据 comboBox 当前索引的字段,升序model->select(); // 重新执行查询,应用排序
}void MainWindow::on_radioButtonDesc_clicked()
{model->setSort(ui->comboBoxSort->currentIndex(), Qt::DescendingOrder); // 设置排序:根据 comboBox 当前索引的字段,降序model->select(); // 重新执行查询,应用排序
}void MainWindow::on_comboBoxSort_currentIndexChanged(int index)
{if (ui->radioButtonAsc->isChecked()) // 如果升序按钮被选中{model->setSort(ui->comboBoxSort->currentIndex(), Qt::AscendingOrder); // 设置为升序}else if (ui->radioButtonDesc->isChecked()) // 如果降序按钮被选中{model->setSort(ui->comboBoxSort->currentIndex(), Qt::DescendingOrder); // 设置为降序}model->select(); // 重新执行查询,应用排序
}
11、记录过滤

QSqlTableModel的setFilter()函数可设置记录过滤条件

void QSqlTableModel::setFilter(const QString &filter);

字符串类型的参数filter是过滤条件,实际上是select语句里where子句的条件。

void MainWindow::on_radioButtonMale_clicked()
{model->setFilter(" gender='男' "); // 设置过滤条件:只显示性别为“男”的记录ui->statusbar->showMessage(QString("记录条数:%1").arg(model->rowCount())); // 在状态栏显示当前筛选后的记录条数
}void MainWindow::on_radioButtonFemale_clicked()
{model->setFilter("gender='女'"); // 设置过滤条件:只显示性别为“女”的记录ui->statusbar->showMessage(QString("记录条数:%1").arg(model->rowCount())); // 在状态栏显示当前筛选后的记录条数
}void MainWindow::on_radioButtonAll_clicked()
{model->setFilter(""); // 清空过滤条件,显示所有记录ui->statusbar->showMessage(QString("记录条数:%1").arg(model->rowCount())); // 在状态栏显示记录条数
}
http://www.dtcms.com/a/393561.html

相关文章:

  • FastAPI + APScheduler + Uvicorn 多进程下避免重复加载任务的解决方案
  • 数据库造神计划第十八天---事务(1)
  • Docker在Linux中离线部署
  • 面阵vs线阵工业相机的触发方式有什么不同?
  • 【Hadoop】HBase:构建于HDFS之上的分布式列式NoSQL数据库
  • 拉取GitHub源码方式
  • 【国二】【C语言】改错题中考察switch的用法、do while执行条件的用法
  • 23种设计模式之【命令模式模式】-核心原理与 Java 实践
  • APP持续盈利:简单可行实行方案
  • qt 操作pdf文档小工具
  • Web3 开发者周刊 68 | EF 将成立一个新的 AI 团队
  • [OpenGL]相机系统
  • 软件体系结构——负载均衡
  • Unity 游戏引擎中 HDRP(高清渲染管线) 的材质着色器选择列表
  • 系统架构设计师(现代计算机系统架构和软件开发)错题集
  • 七、Linux创建自己的proc文件
  • 理解CSS中的100%和100vh
  • [特殊字符] Chrome浏览器证书导入指南
  • 15-用户登录案例
  • Kurt-Blender零基础教程:第3章:材质篇——第1节:材质基础~原理化BSDF,添加有纹理材质与用蒙版做纹理叠加
  • 南京大学 - 复杂结构数据挖掘(一)
  • 嵌入式系统、手机与电脑:一场技术演化的“三角关系”
  • Go语言常用的第三方开发包教程合集
  • 鸿蒙Next ArkTS卡片进程模型解析:安全高效的UI组件隔离之道
  • ubuntu linux 控制wifi功能 dbus控制
  • `TensorBoard`、`PyTorchViz` 和 `HiddenLayer` 深度学习中三个重要的可视化工具
  • 本地设备ipv6默认网关和路由器ipv6默认网关的区别
  • 云原生docker在线yum安装
  • LeetCode 384 打乱数组 Swift 题解:从洗牌算法到实际应用
  • 计算机网络-因特网