(8)Qt---数据库

news2024/12/23 15:28:30

目录

1. Qt数据库简介

2. 连接与关闭

3. 建表

4. 增删改

5. 查询

6.银行管理系统程序代码(包含增删改查)


1. Qt数据库简介

Qt只是作为媒介去操作数据库,本身不具备数据库的功能,因此除了Qt以外,还需要在计算机中安装对应的数据库软件,但是由于SQLite数据库比较轻巧,因此Qt集成了SQLite数据库,此数据库是嵌入式中最常用的数据库。

实际上Qt支持以下类型的数据库产品:

在Qt项目中使用数据库必须在.pro项目配置文件中增加sql模块。

2. 连接与关闭

主要使用到的类是数据库连接类QSqlDatabase(数据库的连接)和数据库错误信息类QSqlError(可能出现的错误信息),涉及的函数有:

// 获得一个基于SQLite的数据库连接对象
QSqlDatabase QSqlDatabase::addDatabase("QSQLITE") [static]
// 设置SQLite数据库文件的名称(不同的数据库此函数表示不同的功能)
// 在运行之后,此文件会在构建目录中生成
void QSqlDatabase::setDatabaseName(const QString & name)
// 打开数据库连接
// 返回值是打开的结果,如果打开失败,可以通过lastError()函数获得错误信息
bool QSqlDatabase::open()
// 获得上一次数据库的错误信息
QSqlError QSqlDatabase::lastError() const
// 可以通过下面的函数把错误信息转换为字符串(实际上这些信息来自于底层数据库)
QString QSqlError::text() const
// 判断连接是否打开
bool QSqlDatabase::isOpen() const
// 关闭连接
void QSqlDatabase::close()

连接成功后会生成数据库文件。

3. 建表

QSqlQuery主要用于执行SQL语句,相关函数如下。

// 执行SQL语句
// 参数是要执行的SQL语句
// 返回值是语句本身执行的结果,并不是数据操作的结果
bool QSqlQuery::exec(const QString & query)
// 用法与之前的同名函数完全相同
QSqlError QSqlQuery::lastError() const

参考建表语句:

CREATE TABLE customer(id INTEGER PRIMARY KEY,name TEXT,money REAL,rate REAL);

建表成功后,可以直接到构建目录中使用SQLiteSpy工具打开.db文件验证是否建表成功。

 dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QtWidgets>
#include <QDebug>
#include <QButtonGroup>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    Ui::Dialog *ui;
    QButtonGroup *group;
    QSqlDatabase db;  //数据库连接对象
    void connect2Db(); //连接到数据库
    void createTable(); //建表

private slots:
    void btnsClickedSlot(int); //按钮组点击槽函数
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);

    group = new QButtonGroup(this);
    group->addButton(ui->pushButtonInsert,1);
    group->addButton(ui->pushButtonDelete,2);
    group->addButton(ui->pushButtonUpdate,3);
    group->addButton(ui->pushButtonSelect,4);

    connect(group,SIGNAL(buttonClicked(int)),this,SLOT(btnsClickedSlot(int)));
    connect2Db();
}

void Dialog::btnsClickedSlot(int id){
    if(id == 1){

    }else if(id == 2){

    }else if(id == 3){

    }else if(id == 4){

    }
}

Dialog::~Dialog()
{
    //如果数据库连接打开了,则关闭
    if(db.isOpen()){
        db.close();
    }
    delete ui;
}

void Dialog::connect2Db()
{
    //获得一个基于SQLite的数据库连接对象
    db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("bank_manage.db");  //设置数据库文件的名称
    //打开链接
    //bool QSqlDatabase::open();  //lasterror函数获得错误信息
    if(db.open()){
        qDebug()<<"连接打开成功!";
        createTable();
    }else{
        //拿到错误信息
        QString text = db.lastError().text();
        //展示错误信息
        QMessageBox::critical(this,"错误",text);

    }

}

void Dialog::createTable()
{
    QString sql = "CREATE TABLE customer(id INTEGER PRIMARY KEY,name TEXT,money REAL,rate REAL)";
    //数据库操作类
    QSqlQuery sq;
    if(sq.exec(sql)){   //执行SQL的成功or失败
        qDebug()<<"建表成功!";
    }else{
        qDebug()<<sq.lastError().text(); //输出错误信息
    }
}

运行结果:

4. 增删改

增删改的操作方法比较相似,需要注意是不要使用拼接的方式创建带参数的SQL语句,原因有:

  • 拼接复杂,容易出错
  • 容易引发SQL注入的安全问题

Qt使用占位符替换的方式“拼接”SQL语句,占位符替换有两种方式:

  • ODBC style (?)
  • Oracle style colon-name 

本次授课使用前者,后者可以查看下面函数的文档。

预处理→绑定→执行

// 预处理带有占位符的SQL语句
// 参数为预处理的SQL语句
// 返回值是预处理的结果
bool QSqlQuery::prepare(const QString & query)
// 添加绑定数据
// 参数为要绑定的数据,各种类型直接传递即可,传递的顺序要按照?的顺序
void QSqlQuery::addBindValue(const QVariant & val)
// 执行预处理的SQL语句
// 语句本身是否成功执行
bool QSqlQuery::exec()

5. 查询

查询与迭代器指针的工作原理类似,相关函数如下。

// 取出结果中的下一个记录,如果没有下一个记录则返回false
bool QSqlQuery::next()
// 按照列序号取出对应的列数据
// 参数是列序号,从0开始
// 返回值是取出的数据,支持各种常见类型的转换
QVariant QSqlQuery::value(int index) const
// 按照列名取出对应的列数据
// 参数是列名
// 返回值是取出的数据,支持各种常见类型的转换
QVariant QSqlQuery::value(const QString & name) const

6.银行管理系统程序代码(包含增删改查)

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QtWidgets>
#include <QDebug>
#include <QButtonGroup>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    Ui::Dialog *ui;
    QButtonGroup *group;
    QSqlDatabase db;  //数据库连接对象
    void connect2Db(); //连接到数据库
    void createTable(); //建表
    void insertData(); //插入
    void deleteData(); //删除
    void updateData(); //更新
    void selectAll(); //查询所有
    bool isDataExists(int); //判断某个id的数据在不在

private slots:
    void btnsClickedSlot(int); //按钮组点击槽函数
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);

    group = new QButtonGroup(this);
    group->addButton(ui->pushButtonInsert,1);
    group->addButton(ui->pushButtonDelete,2);
    group->addButton(ui->pushButtonUpdate,3);
    group->addButton(ui->pushButtonSelect,4);

    connect(group,SIGNAL(buttonClicked(int)),this,SLOT(btnsClickedSlot(int)));
    connect2Db();
}

void Dialog::btnsClickedSlot(int id){
    if(id == 1){
        insertData();

    }else if(id == 2){
        deleteData();

    }else if(id == 3){
        updateData();

    }else if(id == 4){
        selectAll();

    }
}

Dialog::~Dialog()
{
    //如果数据库连接打开了,则关闭
    if(db.isOpen()){
        db.close();
    }
    delete ui;
}

void Dialog::connect2Db()
{
    //获得一个基于SQLite的数据库连接对象
    db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("bank_manage.db");  //设置数据库文件的名称
    //打开链接
    //bool QSqlDatabase::open();  //lasterror函数获得错误信息
    if(db.open()){
        qDebug()<<"连接打开成功!";
        createTable();
    }else{
        //拿到错误信息
        QString text = db.lastError().text();
        //展示错误信息
        QMessageBox::critical(this,"错误",text);

    }

}

void Dialog::createTable()
{
    QString sql = "CREATE TABLE customer(id INTEGER PRIMARY KEY,name TEXT,money REAL,rate REAL)";
    //数据库操作类
    QSqlQuery sq;
    if(sq.exec(sql)){   //执行SQL的成功or失败
        qDebug()<<"建表成功!";
    }else{
        //输出错误信息
        qDebug()<<sq.lastError().text(); //输出错误信息
    }
}

void Dialog::insertData()
{
    //如果姓名不输入,引导用户输入
    QString name = ui->lineEdit->text();
    if(name == ""){
        QMessageBox::warning(this,"提示","请输入名称!");
        return;
    }
    int id = ui->spinBox->value();
    double money = ui->doubleSpinBoxCK->value();
    double rate = ui->doubleSpinBoxLL->value();

    //操作类对象
    QSqlQuery sq;
    //预处理的SQL语句
    QString sql = "INSERT INTO customer VALUES(?,?,?,?)";
    //预处理
    sq.prepare(sql);
    //绑定数据(顺序不能乱)
    sq.addBindValue(id);
    sq.addBindValue(name);
    sq.addBindValue(money);
    sq.addBindValue(rate);
    //真正执行SQL语句,执行的是内部预处理的语句
    if(sq.exec()){
        QMessageBox::information(this,"通知","成功插入一条数据!");

    }else{
        QString text = sq.lastError().text();
        QMessageBox::warning(this,"提示",text);
    }
}

void Dialog::deleteData()
{
    int id = ui->spinBox->value();
    // 判断数据在不在
    if(!isDataExists(id)){
        QMessageBox::warning(this,"提示","数据不存在!");
        return;
    }
    QString sql = "DELETE FROM customer WHERE id=?";
    QSqlQuery sq;
    sq.prepare(sql);
    sq.addBindValue(id);
    if(sq.exec()){
        QMessageBox::information(this,"通知","成功删除一条数据!");

    }else{
        QString text = sq.lastError().text();
        QMessageBox::warning(this,"提示",text);
    }

}

void Dialog::updateData()
{
    //如果姓名不输入,引导用户输入
    QString name = ui->lineEdit->text();
    if(name == ""){
        QMessageBox::warning(this,"提示","请输入名称!");
        return;
    }
    int id = ui->spinBox->value();
    //判断要更新的数据在不在
    if(!isDataExists(id)){
        QMessageBox::warning(this,"提示","数据不存在!");
        return;
    }
    double money = ui->doubleSpinBoxCK->value();
    double rate = ui->doubleSpinBoxLL->value();

    //操作类对象
    QSqlQuery sq;
    //预处理的SQL语句
    QString sql = "UPDATE customer SET name=?,money=?,rate=? WHERE id=?";
    //预处理
    sq.prepare(sql);
    //绑定
    sq.addBindValue(name);
    sq.addBindValue(money);
    sq.addBindValue(rate);
    sq.addBindValue(id);
    //执行
    if(sq.exec()){
        QMessageBox::information(this,"通知","成功修改一条数据!");

    }else{
        QString text = sq.lastError().text();
        QMessageBox::warning(this,"提示",text);
    }
}

void Dialog::selectAll()
{
    QString sql = "SELECT * FROM customer";
    QSqlQuery sq;
    if(sq.exec(sql)){
        //清空上次显示的结果
        ui->textBrowser->clear();
        while(sq.next()){  //判断后面有没有数据
            //取出每列的数据
            //方式一:按照列序号(0,1,2...)取出
            QString id = sq.value(0).toString();
            //方式二:按照列名取出
            QString name = sq.value("name").toString();
            QString money = sq.value("money").toString();
            QString rate = sq.value("rate").toString();
            QString text;
            text = text+id.append("-")+name.append("-")+money.append("-")+rate;
            //展示数据
            ui->textBrowser->append(text);
        }
    }else{
        QString text = sq.lastError().text();
        QMessageBox::warning(this,"提示",text);
    }
}

bool Dialog::isDataExists(int id)
{
    QString sql = "SELECT * FROM customer WHERE id=?";
    QSqlQuery sq;
    sq.prepare(sql);  //预处理
    sq.addBindValue(id); //绑定
    sq.exec();  //执行
    return sq.next(); //只需要返回后面有没有数据

}

ui界面

 

运行结果

 

 

 

 

 

利用SQLiteSpy.exe查看数据表:

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/514627.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows 11 支持安卓应用

更改系统国家 打开windows自带的搜索&#xff0c;找到更改国家或地区。把地区改成美国。 开启电脑VT 不同电脑开启方式不一样&#xff0c;请搜索&#xff1a;xxx进入BIOS和xxx开启VT打开你电脑的VT。 安装子系统 电脑打开Microsoft Store直接搜是搜不到的&#xff0c; 点…

C/C++的内存管理

C/C的内存管理 1.C/C的内存分布2.C语言的动态内存管理方式&#xff1a;malloc/calloc/realloc/free3. C内存管理方式3.1. new/delete操作内置类型3.2.new和delete操作自定义类型 4.operator new与operator delete函数4.1 operator new与operator delete函数 5.new和delete的实现…

一次查找分子级Bug的经历,过程太酸爽了

“Debugging is like trying to find a needle in a haystack, except the needle is also made of hay.” Debug调试就像是在大片的干草堆中找针一样&#xff0c;只不过针也是由干草制成的。 在软件开发的世界里&#xff0c;偶尔会出现一些非常隐蔽的 Bug&#xff0c;这时候工…

数据结构之“树”——二叉树、红黑树、B树、B+树、B*树

这篇文章主要简单总结下二叉树、红黑树、B树、B树、B*树的基本结构和原理。 一、二叉树 二叉树就是度不超过2的树(每个结点最多有两个子结点)。 二叉树是有序树&#xff08;二叉排序树&#xff09;&#xff0c;若将其左右子树颠倒&#xff0c;则成为另一棵不同的二叉树。 二叉…

MYSQL跨服务器访问数据库 :FEDERATED存储引擎

当想从不同服务器的数据库获取数据时&#xff0c;我们会想到oracle的DBLink&#xff1b;sqlserver的链接访问&#xff08;傻瓜式操作&#xff0c;按照步骤配置即可&#xff09;&#xff0c;那么mysql有没有跨服务器访问的功能呢&#xff1f;答案自然是有的。 博主这就分享给大家…

语音识别-置信度

1.CONFIDENCE ESTIMATION FOR ATTENTION-BASED SEQUENCE-TO-SEQUENCE MODELS FOR SPEECH RECOGNITION : https://arxiv.org/pdf/2010.11428.pdf 1.引言 1&#xff09;.置信度的目的&#xff1a; 在半监督学习和主动学习中&#xff0c;选择较高置信度的数据来进一步提高ASR性能…

JVM学习04:类加载与字节码技术

JVM学习04&#xff1a;类加载与字节码技术 1、类文件结构 一个简单的 HelloWorld.java&#xff1a; //HelloWorld示例 public class HelloWorld {public static void main(String[] args) {System.out.println("hello world");} }执行javac -parameters -d . Hello…

生物识别技术是否会对安全产生挑战?

生物识别技术通过人体独特的生物特征来识别个人身份,包括指纹、虹膜、面部识别、声纹识别等技术。这些技术可以在安全领域得到广泛应用,例如入境控制、安全认证、金融交易等方面。但是,生物识别技术也可能带来安全挑战,具体如下: 数据泄露:生物识别技术需要收集个人生物特…

老杨说运维 | 如何成为卓有成效的管理者(关于AIOps的几点思考)

1966年&#xff0c;管理学领域被誉为“大师中的大师”的彼得德鲁克出版了日后被无数次再版的经典作品——《卓有成效的管理者》。 在书中他提到&#xff1a;管理者的使命就是“卓有成效”&#xff0c;但是卓有成效并非天分赋予&#xff0c;而是可以通过后天学习和实践获取的能力…

python 反编译

步骤1&#xff1a; &#xff08;前置&#xff09;下载pyinstxtractor.py ①将pyinstxtractor.py文件移动到想要解包的文件目录下 ②并在当前目录下输入cmd打开终端&#xff0c;执行>python pyinstxtractor.py 待反编译.exe eg:E:\my_decode>python pyinstxtractor.py …

单向散列函数——获取消息的 “指纹”

目录 什么是单向散列函数散列算法的特征散列算法的用途散列算法的分类密码学哈希和非密码学哈希不安全的密码学哈希算法主流的密码学哈希算法 SHA256散列算法&#xff08;SHA2算法&#xff09;SHA256算法过程SM3散列算法 应该使用哪种单向散列函数呢 什么是单向散列函数 单向散…

【920信号与系统笔记】第二章 连续时间系统的时域分析

连续时间系统的时域分析 2.1引言综述n阶线性系统1.数学模型2.解法古典解法近代时域法&#xff08;卷积法、算子法&#xff09; 叠加积分法1.本质2. 待解决问题 2.2系统方程的算子表示法算子及其运算规则1.微分算子和积分算子2.运算规则3.电容和电感的伏安特性 转移算子1.定义2.…

20230508MTCNN1

多目标检测思路 单目标检测&#xff1a;图片 输入到 模型&#xff0c;模型输出 4个值 为什么模型只能检测单个目标&#xff1f; 因为模型 固定输出4个值&#xff0c;表示 一个目标 如何实现多目标检测&#xff1f;思路&#xff1a;一个一个地数 模型要能够 认识目标&#xff…

LiangGaRy-学习笔记-Day12

1、作业回顾 1.1、判断磁盘利用率 要求&#xff1a; 判断磁盘的使用率&#xff0c;如果超过了90%就警告 [rootNode1 sh]# vim disk_check.sh #!/bin/bash #Author By LiangGaRy #2023年5月9日 #Usage:检测硬盘的使用率 ########################################### #定义一…

蓝奥声核心技术分享——用电插座的安全保护技术(安全计量插座)

1.技术背景 用电插座的安全保护技术主要针对在用电负载接入接出&#xff08;即插拔&#xff09;用电插座的过程&#xff0c;解决瞬态异常监控及安全保护问题。该项技术涉及物联网智能硬件设备与测控技术领域&#xff0c;尤其涉及电能信号监测与用电安全监控的技术领域。 随着…

【Redis高级应用】分布式缓存

文章目录 单机Redis存在的问题Redis持久化RDB持久化执行时机RDB原理 AOF持久化AOF原理AOF配置AOF文件重写 RDB与AOF对比 Redis主从搭建主从架构主从数据同步原理全量同步增量同步repl_backlog原理 主从同步优化小结 Redis哨兵哨兵原理集群结构和作用集群监控原理集群故障恢复原…

MySQL多列字段去重的案例实践

同事提了个需求&#xff0c;如下测试表&#xff0c;有code、cdate和ctotal三列&#xff0c; select * from tt;现在要得到code的唯一值&#xff0c;但同时带着cdate和ctotal两个字段。 提起"唯一值"&#xff0c;想到的就是distinct。distinct关键字可以过滤多余的重…

Machine Learning-Ex8(吴恩达课后习题)Anomaly Detection and Recommender Systems

1. Anomaly detection 内容&#xff1a;使用高斯模型来检测数据集中异常的数据&#xff08;概率低的&#xff09;&#xff0c;先在2维数据中进行实验。样本具有两个特征&#xff1a;a. 服务器响应的吞吐量&#xff08;mb/s&#xff09; b. 延迟&#xff08;ms&#xff09;。 …

【linux网络】正则表达式

一、正则表达式 1.1作用范围 通常用于判断语句中&#xff0c;用来检查某一个字符串是否满足某一格式 1.2正则表达式的组成 普通字符包括大小写字母、数字、标点符号及其它符号元字符元字符是指在正则表达式中具有特殊意思的专用字符&#xff0c;可以用来规定其导字符&#…

【P18】JMeter JSON JMESPath Extractor

文章目录 一、准备工作二、测试计划设计 一、准备工作 慕慕生鲜&#xff1a; http://111.231.103.117/#/login 进入网页后&#xff0c;登录&#xff0c;页面提供了账户和密码 搜索框输入“虾” 右键检查或按F12&#xff0c;打开调试工具&#xff0c;点击搜索 二、测试计划设…