c++ Qt 数据库操作

1、准备工作

Qt本身并没有数据库功能,但是Qt支持调用其他主流的数据库产品,并且这些数据库产品统一了Qt的接口,实际上是一种数据库的中间件。

Qt支持以下数据库类型:

嵌入式常用的数据库是sqlite3,本体只有几兆大小。非常适合集成到嵌入式产品中,在Qt5版本及以上也集成了SQLite数据库。因此可以直接通过驱动名称连接SQLite。

数据库编程中需要用到以下几个类:

  • QSqlDatabase

数据库相关类,表示一个数据库连接。

  • QSqlQuery

数据库操作类,可以操作SQL语句

  • QSqlError

数据库错误信息类,用户收集数据库底层传递到Qt中的错误信息。

数据库相关类无法直接使用,需要在.pro配置文件中添加sql模块。

2、连接数据库

主要通过QSqlDatabase类进行连接。相关函数:

1)获得一个数据库连接对象

// 获得一个数据库连接对象
// 参数为数据库类型,详见本章第一节表格(区分大小写)
// 返回值为连接对象
#include <QSqlDatabase>
QSqlDatabase QSqlDatabase:: addDatabase(const QString & type)[static]

2)设置数据库名称

// 设置数据库名称
// 参数因不同的数据库表示不同的涵义。对于SQLite,此函数表示数据库文件名。此文件会在项目中构建目录中生成
void QSqlDatabase:: setDatabaseName(const QString & name)

3)打开数据库连接

// 打开数据库连接
// 返回值为连接打开的结果,如果打开失败,可以通过lastError函数获取错误信息
bool QSqlDatabase:: open()

4)返回上一次的错误信息封装类

错误信息类为QSqlError

// 返回上一次的错误信息封装类
#include <QSqlError>
QSqlError QSqlDatabase:: lastError() const

5)从QSqlError对象中提取错误信息文本

// 从QSqlError对象中提取错误信息文本
#include <QSqlError>
QString QSqlError:: text() const

6)返回数据库连接的打开状态

// 返回数据库连接的打开状态
bool QSqlDatabase:: isOpen() const

7)关闭数据库连接

// 关闭数据库连接
void QSqlDatabase:: close()

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(btnClickedSlots(int)));
    connectD2B();
}
Dialog::~Dialog()
{
    //检查数据库状态
    if(db.isOpen())
    {
        //关闭数据库连接
        db.close();
    }
    delete ui;
}
//连接数据库
void Dialog::connectD2B()
{
    //获取数据库连接对象
    db = QSqlDatabase::addDatabase("QSQLITE");
    //设置数据库名称
    db.setDatabaseName("book_management.db");
    //打开数据库连接
    bool ret = db.open();
    if(ret == true)
    {
        qDebug()<<"打开成功";
    }
    else
    {
        qDebug()<<"打开失败";
        //返回最近错误信息封装类
        QSqlError errorInfo = db.lastError();
        //从错误信息类提取错误信息
        QString text = errorInfo.text();
        //弹窗显示错误信息
        QMessageBox::critical(this,"错误",text);
    }
}
void Dialog::btnClickedSlots(int id)
{
    if(id == 1)
    {
        qDebug()<<"增加";
    }
    else if(id == 2)
    {
        qDebug()<<"删除";
    }
    else if(id == 3)
    {
        qDebug()<<"修改";
    }
    else if(id == 4)
    {
        qDebug()<<"查询";
    }
    else
    {
        qDebug()<<"错误";
    }
}

3、创建表

建表语句(SQL语句):

//表名   id设置为主键 名字文本 价格实数 作者文本
CREATE TABLE book(id INTEGER PRIMARY KEY,name TEXT,price REAL,author TEXT);

CREATE TABLE book(
    id INTEGER PRIMARY KEY,
    name TEXT,
    price REAL,
    author TEXT
);

查看建表是否成功

// 执行SQL语句
// 参数为SQL语句内容
// 返回值为执行的结果,只关心是否成功,其他不管
bool QSqlQuery:: exec(const QString & query)

错误信息

// 与本章第2节的同名函数用法完全一样
QSqlError QSqlQuery::lastError() const

一个操作SQLite的可视化软件

++下载链接:百度网盘 请输入提取码 提取码:hqyj 

//创建表(建表)
void Dialog::creatTable()
{
    //方法1       //表名   id设置为整形主键 名字文本 价格实数 作者文本
     QString sql ="CREATE TABLE book(id INTEGER PRIMARY KEY,name TEXT,price REAL,author TEXT);";
    //方法2
    sql = QString("CREATE TABLE book(\//表名 \
                    id INTEGER PRIMARY KEY,\//id设置为整形主键\
                    name TEXT,\//名字 文本\
                    price REAL,\//价格  实数\
                    author TEXT);\//作者     文本\
                    ");   
    //创建数据库操作
    QSqlQuery sq;
    //执行SQL语句,并检查是否创建表成功
    if(sq.exec(sql))
    {
        qDebug()<<"建表成功";
    }
    else// 建表失败,注意:建表成功或失败都很正常,如果要建的表已经存在,就会建表失败

    {
        //获取错误信息封装类
        QSqlError errorInfo = sq.lastError();
        //从错误信息封装类获取错误信息
        QString text = errorInfo.text();
        qDebug()<<"建表失败"<<text;
    }
}

4、增删改

增删改都需要先录入用户输入,然后把用户输入的数据组装成SQL语句,最后执行。

组装SQL语句有两种方式:

  • 字符串拼接

这种方式实现简单,但是容易拼接错误,且安全性较低。

  • 预处理+占位符

推荐使用这种方式,这种方式需要先编写占位符。预处理SQL语句,交给Qt,Qt内部就知道要执行的SQL语句格式,然后在进行参数和占位符的替换,最终执行。

占位符有两种表示风格:

  • Oracle风格

使用:字段的格式

UPDATE book SET name=:name,price=:price,author=:author WHERE id=:id;

  • ODBC风格

使用?的格式

INSERT INTO book VALUES(?,?,?,?);

预处理SQL语句,此时SQL语句并没有执行,只是送入到了Qt内部。

// 预处理SQL语句,此时SQL语句并没有执行,只是送入到了Qt内部。
// 参数为预处理的SQL语句
// 返回值预处理的结果
bool QSqlQuery:: prepare(const QString & query)

绑定ODBC风格的占位符参数,绑定的时候一定要注意顺序。

// 绑定ODBC风格的占位符参数,绑定的时候一定要注意顺序。
// 参数为要绑定的数据
void QSqlQuery:: addBindValue(const QVariant & val)

增加操作

void Dialog::insertData()
{
    QString name = ui->lineEdit->text();
    if(name == "")
    {
        QMessageBox::warning(this,"提示","请输入书名");
        return;
    }
    QString author = ui->lineEditAuthor->text();
    if(author == "")
    {
        QMessageBox::warning(this,"提示","请输入作者名");
        return;
    }
    int id = ui->spinBox->value();
    double price = ui->doubleSpinBox->value();
    // 预处理的SQL语句
    QString sql = "INSERT INTO book VALUES(?,?,?,?);";
    // 预处理
    QSqlQuery sq;
    sq.prepare(sql);
    // 绑定数据
    sq.addBindValue(id);
    sq.addBindValue(name);
    sq.addBindValue(price);
    sq.addBindValue(author);·
    // 执行绑定好的SQL语句,并检查执行状态
    if(sq.exec())
    {
        QMessageBox::information(this,"通知","数据插入成功");
    }
    else
    {
        // 获取错误信息封装类
        QSqlError info = sq.lastError();
        QString text = info.text();
        QMessageBox::warning(this,"警告","数据插入失败");
    }
}

绑定Oracle风格的占位符参数,绑定可以乱序

// 绑定Oracle风格的占位符参数,绑定可以乱序
// 参数1:占位符
// 参数2:要绑定的数据
void QSqlQuery:: bindValue(const QString & placeholder, const        QVariant & val)

删除操作

// 删除, 按照id删除
void Dialog::deleteData()
{
    int id = ui->spinBox->value();
    // 查询表中id是否存在
    // TODO --

    // 预处理的SQL语句
    QString sql = "DELETE FROM book WHERE id=?";
    QSqlQuery sq;
    sq.prepare(sql); // 预处理

    // 绑定参数
    sq.addBindValue(id);
    // 执行绑定后SQL语句
    if(sq.exec())
    {
        QMessageBox::information(this,"通知","数据删除成功");
    }
    else
    {
        // 获得错误信息封装类
        QSqlError info = sq.lastError();
        QString text = info.text();
        QMessageBox::critical(this,"错误",text);
    }

}

更改操作

//按编号修改数据
void Dialog::updateDate()
{
    //获得用户输入的数据,(全部获得)
    QString name = ui->lineEdit->text();
    if(name == "")
    {
        QMessageBox::warning(this,"提示","请输入书名");
        return;
    }
    QString author = ui->lineEditAuthor->text();
    if(author == "")
    {
        QMessageBox::warning(this,"提示","请输入作者名");
        return;
    }
    int id = ui->spinBox->value();
    double price = ui->doubleSpinBox->value();
    //判断ID在数据库中是否存在

    //预处理语句(oracle风格),不需要注意数据顺序
    QString sql = "UPDATE book SET name=:name,price=:price,author=:author WHERE id=:id";
    //预处理
    QSqlQuery sq;
    sq.prepare(sql);
    //绑定参数
    sq.bindValue(":id",id);
    sq.bindValue(":name",name);
    sq.bindValue(":price",price);
    sq.bindValue(":author",author);
    //执行绑定后的SQL语句
    if(sq.exec())
    {
        QMessageBox::information(this,"提示","数据更改成功");
        return;
    }
    else
    {
        //获取错误信息封装
        QSqlError info = sq.lastError();
        QString text = info.text();
        QMessageBox::critical(this,"错误",text);
    }
}

5、查询

5.1 全查

1)判断查询结果有无数据,如果有数据则移动游标取出,没有返回false

// 判断查询结果有无数据,如果有数据则移动游标取出,没有返回false
bool QSqlQuery:: next()

2)按照字段序号取出对应的值,序号从0开始

// 按照字段序号取出对应的值,序号从0开始
// 返回值QVariant类型,可以根据需要直接转换为所需要类型
QVariant QSqlQuery:: value(int index) const

3)按照字段名称取出对应的值

// 按照字段名称取出对应的值
// 返回值QVariant类型,可以根据需要直接转换为所需要类型
QVariant QSqlQuery:: value(const QString & name) const

void Dialog::selectAll()
{
    //清空textBrowser
    ui->textBrowser->clear();
    QString sql = "SELECT * FROM book";
    QSqlQuery sq;
    if(sq.exec(sql))
    {
        while(sq.next())
        {
            //取出一条记录中的每个字段值
            QString id = sq.value(0).toString();
            QString name = sq.value(1).toString();
            QString price = sq.value("price").toString();
            QString author = sq.value("author").toString();
            //显示
            QString text = id.append("-")+name.append("-")+price.append("-")+author;
            ui->textBrowser->append(text);
        }
    }
}

查看id是否存在

bool Dialog::isDateExists(int id)
{
    QString idText = QString::number(id);
    QString sql = "SELECT * FROM book WHERE id=";
    sql.append(idText);
    QSqlQuery sq;
    if(sq.exec(sql))
    {
        return sq.next();
    }
    else
    {
        return false;
    }
}

5.2模糊查询

可以使用LIKE关键字配合两个通配符实现模糊查询。

通配符

  • %

任意多个(0、1、2、3........n)字符

  • _

任意一个字符

【例子】查找‘瑞’ 字辈的信息

SELECT * FROM book WHERE name LIKE "_瑞%"

【例子】查找姓名中包含“瑞”这个字的人员信息。

SELECT * FROM book WHERE name LIKE "%瑞%"

dialog.cpp

//模糊查询
void Dialog::selectLike()
{
    //获取要查询的内容
    QString name = ui->lineEdit->text();
    if(name == "")
    {
        QMessageBox::warning(this,"提示","请输入书名");
        return;
    }
    else
    {
        //预处理
        QString sql = "SELECT * FROM book WHERE name LIKE ?";
        QSqlQuery sq;
        sq.prepare(sql);
        //SQL语句处理,%name%
        sq.addBindValue(name.prepend("%").append("%"));
        if(sq.exec())
        {
            //添加状态位置,检查是否查询到结果
            bool reState = true;
            //清空上次查询内容
            ui->textBrowser->clear();
            while(sq.next())
            {
                //数据库数据遍历
                QString id = sq.value(0).toString();
                QString name = sq.value(1).toString();
                QString price = sq.value(2).toString();
                QString author = sq.value(3).toString();
                //显示
                QString text = id.append("-")+name.append("-")+price.append("-")+author;
                ui->textBrowser->append(text);
                reState =false;
            }
            //查询结果判断
            if(reState)
            {
                QMessageBox::information(this,"提示","没有相关结果");
                return;
            }
        }
        else
        {
            //错误信息弹窗
            QSqlError err = sq.lastError();
            QString text = err.text();
            QMessageBox::critical(this,"错误",text);
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

UnityShader玉石效果

效果&#xff1a; 代码&#xff1a; Shader "MyShader/Jade" {Properties{_DiffuseColor("漫反射颜色",color)(1,1,1,1)_ThicknessMap("厚度图",2d)"white"{}_AddColor("叠加颜色",color)(1,1,1,1)_CubeMap("环境贴图…

java实现多级目录树(递归实现)

一.应用场景 有时候需要我们后台给前台传树结构的数据&#xff0c;要怎么查询? 怎么返回数据呢&#xff1f; 二.数据库表设计以及数据内容(以部门举例) id 主键 parent_id 父级部门id depart_name 部门名词 sort 部门排序三.实体类 Data public…

Qt 软件封装与打包

1. Qt 软件封装 1、首先以 release 方式进行编译&#xff0c;将生成的 CloudOne.exe 文件复制到 D:\CloudApp 文件夹&#xff08;自行创建&#xff09; 2、打开 Qt 命令行工具&#xff08;如下图所示&#xff09;&#xff0c;并按顺序输入如下指令 cd D:\CloudApp windeployq…

Spring Boot 笔记 019 创建接口_文件上传

1.1 创建阿里OSS bucket OSS Java SDK 兼容性和示例代码_对象存储(OSS)-阿里云帮助中心 (aliyun.com) 1.2 编写工具类 package com.geji.utils;import com.aliyun.oss.ClientException; import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import com.aliyun…

每日一题——数字翻转

题目; 这道题看似是很简单的回文数 实则就是很简单的回文数 但是需要注意的一点是负数 可以在开头就进行判断&#xff0c;如果N<0的话就令N-N&#xff0c;将所有数都转成正数就好办了 上代码&#xff1a; #include <iostream> #include<string> #include<…

算法沉淀——哈希算法(leetcode真题剖析)

算法沉淀——哈希算法 01.两数之和02.判定是否互为字符重排03.存在重复元素04.存在重复元素 II05.字母异位词分组 哈希算法&#xff08;Hash Algorithm&#xff09;是一种将任意长度的输入&#xff08;也称为消息&#xff09;映射为固定长度的输出的算法。这个输出通常称为哈希…

Spring Security学习(四)——登陆认证(包括自定义登录页)

前言 和前面的文章隔了很长时间才更新Spring Security系列&#xff0c;主要原因一个是之前太忙了&#xff0c;把项目都忙完了&#xff0c;赶上春节假期&#xff0c;就慢慢研究。Spring Security的体系非常复杂&#xff0c;一口吃不了热豆腐&#xff0c;没办法速成&#xff0c;…

微服务—ES数据同步

目录 数据同步 问题分析 方案1. 同步调用 方案2. 异步通知 方案3. 监听binlog​编辑 各方案对比 案例——利用MQ实现数据同步 步骤1. 导入hotel-admin项目 步骤2. 声明交换机、队列 步骤3. 发送MQ消息 步骤4. 接收MQ消息 步骤5. 测试同步功能 数据同步 elasticsea…

八、键盘响应

之前博文格式已经固定&#xff0c;这里就不在赘述了&#xff0c;直接把核心代码进行解释一下即可&#xff0c;仅作为小笔记而已 项目实现功能&#xff1a; 按下键盘0&#xff0c;显示原始图像 按下键盘1&#xff0c;显示原始图像的灰度图 按下键盘2&#xff0c;显示原始图像的…

Python-To-Do-List

今天跟着油管学习创建了简单的代办事项列表应用程序&#xff0c;使用了python的tkinter库来制作图形用户界面&#xff08;GUI&#xff09; 1. 导入tkinter库 python Copy code import tkinter from tkinter import * 这两行导入了tkinter模块&#xff0c;它是Python的标准GUI库…

六、Redis之数据持久化及高频面试题

6.1 数据持久化 官网文档地址&#xff1a;https://redis.io/docs/manual/persistence/ Redis提供了主要提供了 2 种不同形式的持久化方式&#xff1a; RDB&#xff08;Redis数据库&#xff09;&#xff1a;RDB 持久性以指定的时间间隔执行数据集的时间点快照。AOF&#xff0…

django CBV 与 DRF APIView源码分析

django CBV源码分析 在django框架中&#xff0c;视图层中的逻辑即可以使用函数处理也可以使用类进行处理&#xff0c;如果在视图层中使用函数处理请求&#xff0c;就是FBV(function base views)&#xff0c;如果在视图层中使用类处理请求&#xff0c;就是CBV(class base views…

微信,支付宝在线换钱平台系统源码

探索全新、全开源的在线换钱系统源码&#xff0c;它将以前所未有的方式改变您的支付体验。我们为您精心打造了一个集简单易用与安全高效于一身的优质产品&#xff0c;它采用最新的技术开发&#xff0c;为您带来前所未有的便捷与安心。 这款在线换钱系统源码设计直观&#xff0…

【大数据Hive】hive 表设计常用优化策略

目录 一、前言 二、hive 普通表查询原理 2.1 操作演示说明 2.1.1 创建一张表&#xff0c;并加载数据 2.1.2 统计3月24号的登录人数 2.1.3 查询原理过程总结 2.2 普通表结构带来的问题 三、hive分区表设计 3.1 区表结构 - 分区设计思想 3.2 操作演示 3.2.1 创建分区表…

每日一题(数字颠倒,单词倒排)

数字颠倒_牛客题霸_牛客网 (nowcoder.com) #include <stdio.h>int main() {char arr[100];gets(arr);int lenstrlen(arr);for(int ilen-1;i>0;i--){printf("%c",arr[i]);}return 0; } 单词倒排_牛客题霸_牛客网 (nowcoder.com) #include <stdio.h> #…

《Java 简易速速上手小册》第4章:Java 中的异常处理(2024 最新版)

文章目录 4.1 异常类型和错误 - 遇见你的小怪兽4.1.1 基础知识4.1.2 重点案例&#xff1a;文件读取处理4.1.3 拓展案例 1&#xff1a;处理空指针异常4.1.4 拓展案例 2&#xff1a;捕获多个异常 4.2 异常处理机制 - 穿上你的超级英雄斗篷4.2.1 基础知识4.2.2 重点案例&#xff1…

Vuex 模块的详解

Vuex 模块是将 store 分割成多个模块的一种方式&#xff0c;每个模块都有自己的状态、mutations、actions 和 getters。这有助于更好地组织和管理应用程序的状态。 创建模块&#xff1a; 首先&#xff0c;需要创建一个模块。可以在 store 中定义一个新的模块对象&#xff0c…

python小项目----多重剪切板

代码&#xff1a; import shelve,pyperclip,sysimport mcbmcbShelfshelve.open(mcb)# 保存剪切板内容 if len(sys.argv)3 and sys.argv[1].lower()save:#剪切板的内容保存到第三个参数中mcbShelf[sys.argv[2]]pyperclip.paste()print("你的剪切板中的内容将被保存到mcbSh…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 2月14日,星期三

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年2月14日 星期三 农历正月初五 1、 第十四届全国冬季运动会将于17日开幕&#xff0c;部分赛事今天起陆续开赛。 2、 2024年购房政策将进一步宽松&#xff0c;专家称今年买房性价比更高。 3、 春节档票房突破45亿元&#…

算法学习——LeetCode力扣回溯篇2

算法学习——LeetCode力扣回溯篇2 40. 组合总和 II 40. 组合总和 II - 力扣&#xff08;LeetCode&#xff09; 描述 给定一个候选人编号的集合 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字…