Qt中操作SQLite数据库

news2024/11/15 7:33:51

0.前言

SQLite是一款开源、轻量级、跨平台的数据库,无需server,无需安装和管理配置。它的设计目标是嵌入式的,所以很适合小型应用,也是Qt应用开发种常用的一种数据库。

1.驱动

Qt SQL模块使用驱动程序插件(plugins)与不同的数据库API进行通信。由于Qt的SQL模块API与数据库无关,因此所有特定于数据库的代码都包含在这些驱动程序中。Qt提供了几个驱动程序,也可以添加其他驱动程序。提供驱动程序源代码,可用作编写自己的驱动程序的模型。

QtCreator在*.pro中引入sql模块(QT+=sql),或是VS中在Qt VS Tool里勾选上sql模块,就可以使用该模块的接口了。

可以使用QSqlDatabase::drivers()获取驱动程序列表并打印,Qt5.9.7输出如下:

其中,SQLite是一个进程内数据库,这意味着没有必要拥有数据库服务器。SQLite在单个文件上运行,在打开连接时必须将其设置为数据库名称。如果该文件不存在,SQLite将尝试创建它。。

2.初相遇

/*
 * ... ...
 * 我喜欢那样的梦
 * 在梦里 一切都可以重新开始
 * 一切都可以慢慢解释
 * 心里甚至还能感觉到所有被浪费的时光
 * 竟然都能重回时的狂喜和感激
 * ... ...
 * 
 *                ----席慕容《初相遇》
 */


#include <QSqlDatabase>
#include <QDebug>

void initDb()
{   
    //qDebug()<<QSqlDatabase::drivers();//打印驱动列表
    QSqlDatabase db;
    //检测已连接的方式 - 默认连接名
    //QSqlDatabase::contains(QSqlDatabase::defaultConnection)
    if(QSqlDatabase::contains("qt_sql_default_connection"))
        db = QSqlDatabase::database("qt_sql_default_connection");
    else
        db = QSqlDatabase::addDatabase("QSQLITE");
    //检测已连接的方式 - 自定义连接名
    /*if(QSqlDatabase::contains("mysql_connection"))
        db = QSqlDatabase::database("mysql_connection");
    else
        db = QSqlDatabase::addDatabase("QSQLITE","mysql_connection");*/
    //设置数据库路径,不存在则创建
    db.setDatabaseName("sqltest.db");
    //db.setUserName("gongjianbo");  //SQLite不需要用户名和密码
    //db.setPassword("qq654344883");
    
    //打开数据库
    if(db.open()){
        qDebug()<<"open success";
        //关闭数据库
        db.close();
    }
    
}

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QT嵌入式开发,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

上面的代码中,先是创建了一个QSqlDatabase对象,该类用于处理数据库的连接。contains方法用于查看给定的连接名称是否在连接列表中,database方法获取数据库连接,前提是已使用addDatabase添加数据库连接。addDatabase声明如下:

QSqlDatabase QSqlDatabase::addDatabase(const QString &type, const QString &connectionName = QLatin1String(defaultConnection)) [static]

第一个参数对应驱动名,第二个参数为连接名称 ,如果不使用默认连接名称“qt_sql_default_connection”的话需要填写该参数。

设置了驱动及连接名称后,就是设置数据库文件的名称/路径,因为SQLite不需要用户名和密码,接下来直接就可以通过open和close函数来打开关闭该数据库了。

此外,如果需要在内存中创建数据库,而不是指定一个文件,可以setDatabaseName(“:memory:”);

db.setDatabaseName(":memory:");

3.创建表

SQL语句执行需要用到QSqlQuery类,文档有云:

QSqlQuery封装了在QSqlDatabase上执行的SQL查询中创建,导航和检索数据所涉及的功能。它可以被用来执行DML(数据操纵语言)语句,例如select、insert、update、delete,以及DDL(数据定义语言)语句,如create table,还可以用于执行非标准SQL的特定于数据库的命令。

成功执行的SQL语句将查询的状态设置为活动状态,以便isActive()返回true。否则,查询的状态将设置为非活动状态。在任何一种情况下,执行新的SQL语句时,查询都位于无效记录上。必须先将活动查询导航到有效记录(以便isActive()返回true),然后才能检索值。

#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>

void createTable()
{
    //sql语句不熟悉的推荐《sql必知必会》,轻松入门
    //如果不存在则创建my_table表
    //id自增,name唯一
    const QString sql=R"(
                      CREATE TABLE IF NOT EXISTS  my_table (
                      id   INTEGER   PRIMARY KEY AUTOINCREMENT NOT NULL,
                      name CHAR (50) UNIQUE NOT NULL,
                      age  INTEGER
                      );)";
    //QSqlQuery构造前,需要db已打开并连接
    //未指定db或者db无效时使用默认连接进行操作
    QSqlQuery query;
    
    if(query.exec(sql)){
        qDebug()<<"init table success";
    }else{
        //打印sql语句错误信息
        qDebug()<<"init table error"<<query.lastError();
    }
}

代码通过QSqlQuery的exec方法执行SQL语句,创建了一个简单的数据表。exec执行SQL语句成功返回true,否则返回false。

QSqlQuery的构造函数可以指定QDatabase参数,如果未指定db,或者db无效将使用默认连接。

QSqlQuery::QSqlQuery(QSqlDatabase db);

要注意的是,对于SQLite,exec方法一次只能执行一个语句

4.执行增删改查

执行了上面的操作且数据库已open,就能使用QSqlQuery的exec方法来完成增删改查了。

//插入数据
void insertRecord(const QString &name, int age)
{
    QSqlQuery query;
    //方式一,直接执行SQL语句
    query.exec(QString(R"(INSERT INTO my_table(name,age) VALUES('%1',%2);)")
               .arg(name).arg(age));
    //方式二,绑定值,待定变量默认用问号占位,注意字符串也没有引号
    /*query.prepare(R"(INSERT INTO my_table(name,age) VALUES(?,?);)");
    query.addBindValue(name);
    query.addBindValue(age);
    query.exec();*/
}

//删除数据
void deleteRecord(const QString &name)
{
    QSqlQuery query;
    //方式一,直接执行SQL语句
    query.exec(QString(R"(DELETE FROM my_table WHERE name='%1';)")
               .arg(name));
    //方式二,绑定值,待定变量默认用问号占位
    /*query.prepare(R"(DELETE FROM my_table WHERE name=?;)");
    query.addBindValue(name);
    query.exec();*/
}

//更新数据
void updateRecord(const QString &name, int age)
{
    QSqlQuery query;
    //方式一,直接执行SQL语句
    query.exec(QString(R"(UPDATE my_table SET age=%2 WHERE name='%1';)")
               .arg(name).arg(age));
    //方式二,绑定值,待定变量默认问号,可自定义
    /*query.prepare(R"(UPDATE my_table SET age=:age WHERE name=:name;)");
    query.bindValue(":name",name);//通过自定义的别名来替代
    query.bindValue(":age",age);
    query.exec();*/
}

//查询数据
int searchRecord(const QString &name)
{
    QSqlQuery query;
    query.exec(QString(R"(SELECT age FROM my_table WHERE name='%1';)")
               .arg(name));

    //获取查询结果的第0个值,
    //如果结果是多行数据,可用while(query.next()){}遍历每一行
    int ageValue=-1;
    if(query.next()){
        ageValue=query.value(0).toInt();
    }
    qDebug()<<ageValue;
    return ageValue;
}

可以看到,如果熟悉SQL语句的话,很容易就实现了增删改查功能。

对于 BLOB 类型,查询后可以 toByteArray,修改时可以 bindValue QByteArray。

5.进阶

有时候会遇到大量数据操作的情况,这时候用普通的insert之类的语句循环操作可能会很慢。

技巧一:开启事务

SQLite通过执行”BEGIN;“或是”BEGIN TRANSACTION;“开启事务,执行”ROLLBACK;“进行回滚,执行”COMMIT;“或是”END TRANSACTION;“提交事务。QSqlDatabase也提供了对应的transaction、rollback、commit三个函数来执行对应操作。

技巧二:关闭写同步(synchrnous)

在SQLite中,数据库配置的参数都由编译指示(pragma)来实现的,而其中synchronous选项有三种可选状态,分别是full、normal、off。简要说来,full写入速度最慢,但保证数据是安全的,不受断电、系统崩溃等影响,而off可以加速数据库的一些操作,但如果系统崩溃或断电,则数据库可能会损毁。通过执行”PRAGMA synchronous = OFF;“语句,可以提升效率,不过若不是临时数据库不建议此操作。

SQLite 默认是文件锁, Qt 中 SQLite 默认是以多线程读写模式打开,如果同时写入就会出现写入错误:

可以将写操作上锁,但是实测线程中循环写入时,只读打开去查询也是会阻塞很久,毫秒到几秒不等,这时候就得把超时设置长一点。

所以还是得读写都加锁,但这也只能解决单个进程的并发访问。

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QT嵌入式开发,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

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

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

相关文章

多线程与高并发(一)

【前言】&#xff1a; 多线程、JVM、操作系统。 【概述】&#xff1a; 基础概念 JUC同步工具 同步容器 Disruptor //一个MQ框架&#xff0c;公认的单机环境下效率最高。 线程池 【线程的概念】&#xff1a; 【纤程】&#xff1a; 【 run和start的区别 】&#xff1a; //n…

[附源码]Python计算机毕业设计SSM家用饰品在线销售系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【面试问题】进程和线程的区别——通俗易懂

1. ”进程“是什么1.2 管理进程1.3 内存管理1.4 进程间通信2. 线程是什么3.进程和线程的区别1. ”进程“是什么 在对比"进程"和"线程"两者之间的区别前,我们需要先了解什么是"进程"?什么是"线程"? **“进程”(process)也叫"任…

HIFI测序揭示拟南芥MSH1参与介导的细胞器基因组重组与变异积累规律

近日&#xff0c;中国农业科学院农业基因组所武志强课题组在《The Plant Journal》在线发表了题为“Long-read sequencing characterizes mitochondrial and plastid genome variants in Arabidopsis msh1 mutants”的研究论文&#xff0c;该研究通过高精度的长读长测序&#x…

安卓APP源码和设计报告——仿淘宝水果商城

项目名称 仿淘宝水果商城项目概述 随着互联网技术地高速发展&#xff0c;计算机进入到每一个人的生活里&#xff0c;从人们的生活方式到整个社会的运转都产生了巨大的变革&#xff0c;而在信息技术发达的今天&#xff0c;互联网的各种娱乐方式都在渗透到人们的生活方式之中&…

Procreate绘画教程

Procreate绘画教程 从 30 多年的设计师/插画家那里彻底有效地学习 Procreate&#xff01;已更新至 Procreate 5.2&#xff01; 课程英文名&#xff1a;Procreate Solid Foundations 此视频教程共10.0小时&#xff0c;中英双语字幕&#xff0c;画质清晰无水印&#xff0c;源码…

三条建议!让您在世界杯期间确保网络安全!

2022年11月&#xff0c;全球的目光都聚焦在依旧“夏日炎炎”的卡塔尔。随着人们观看、分享赛事的习惯从传统的电视转为网络&#xff0c;世界杯必将成为整个2022年的“流量王”。在我国&#xff0c;仅仅德国与日本的一场比赛在微博平台就带来了13.8亿次阅读。 据估计&#xff0…

细粒度图像分类论文研读-2020

文章目录Filtration and Distillation: Enhancing RegionAttention for Fine-Grained Visual Categorization(by localization- classification subnetwork)AbstractIntroductionApproachDiscriminative Regions ProposingFeature Learning and Recognition EnsembleFiltration…

Spring源码深度解析:十一、Spring的循环依赖

一、前言 文章目录&#xff1a;Spring源码深度解析&#xff1a;文章目录 这篇文章是接着 Spring源码深度解析&#xff1a;七、bean的加载① - doGetBean 的继续分析过程。 二、什么是循环依赖 循环依赖&#xff0c;其实就是循环引用&#xff0c;就是两个或者两个以上的 bea…

【MySQL】数据处理函数

只有当你开始相信自己时&#xff0c;你才拥有真正的人生。——《洛奇》 前言&#xff1a; 大家好&#xff0c;我是爱打拳的程序猿。今天给大家展示是数据处理函数的用法&#xff0c;分为单行处理函数和分组函数。数据处理函数主要是为了更方便解决数据的各种问题。文章以代码和…

2023年Unity UI教程

2023年Unity UI教程 Unity 新 UI 系统 UI 工具包的完整概述 课程英文名&#xff1a;Modern Unity UI with UI Toolkit 此视频教程共10.0小时&#xff0c;中英双语字幕&#xff0c;画质清晰无水印&#xff0c;源码附件全 下载地址 课程编号&#xff1a;336 百度网盘地址&am…

SSM框架-获取容器的方式

9 容器 9.1 获取容器 记载类路径下的容器所在的配置文件,也就是之前用的 public class App2 {public static void main(String[] args) {ApplicationContext ctx new ClassPathXmlApplicationContext("applicationContext.xml");BookDao bookDao (BookDao) ctx.…

liunx 部署 kkfileview文件预览 以及解决https访问

kkfileview gitee地址 https://gitee.com/kekingcn/file-online-preview 1.下载office组件 wget https://kkfileview.keking.cn/LibreOffice_7.1.4_Linux_x86-64_rpm.tar.gz tar -zxvf LibreOffice_7.1.4_Linux_x86-64_rpm.tar.gz cd LibreOffice_7.1.4.2_Linux_x86-64_rpm/R…

TensorRT推理手写数字分类(一)

系列文章目录 &#xff08;一&#xff09;使用pytorch搭建模型并训练 文章目录系列文章目录前言一、网络搭建1.LeNet网络结构2.pytorch代码二、网络训练1.pytorch代码2.结果展示三、保存和加载模型1.保存整个网络2.保存网络中的参数总结前言 为了学习一下使用TensorRT进行推理…

硬核!Github星标79.4K的阿里强推Java面试参考指南到底有多强?

谈到Java面试&#xff0c;相信大家第一时间脑子里想到的词肯定是金三银四&#xff0c;金九银十。好像大家的潜意识里做Java开发的都得在这个时候才能出去面试&#xff0c;跳槽成功率才高&#xff01;但LZ不这么认为&#xff0c;LZ觉得我们做技术的一生中会遇到很多大大小小的面…

Java并发编程—如何写好代码?链式调用该怎么玩?

目录 一、案例说明 二、原生方式代码流程 三、链式调用代码流程 四、链式调用手搓的方式&#xff1a; 五、总结&#xff1a; 在上一篇博客https://blog.csdn.net/qq_52545155/article/details/128212148?spm1001.2014.3001.5501&#xff0c;博主在写商城统计商品价格的时…

mybatis中其他数据源也使用XML进行操作(SqlSessionFactory.openSession(Connection connection)方法)

文章目录1. 前言2. 先说结论3. 例子1. 准备数据2. 思考过程3. 结论1. 前言 当前在使用springbootmybatis的时候&#xff0c;通常会先在配置文件中配置好数据源&#xff0c;并在Mapper.xml文件编写好相关SQL&#xff0c;使用mybatis进行对数据库进行所谓的crud操作。 有时候会出…

nginx代理https妈妈级手册

目录 背景说明 相关地址 https证书生成 nginx安装及配置 结果展示​编辑 背景说明 为了保证传输加密、访问安全&#xff0c;我们采用nginx服务器将http服务代理为https。所需材料&#xff1a;openssl&#xff08;用来生成证书&#xff09;、http服务、nginx自身。 相关地址…

C/C++第三方库zeromq、log4cpp交叉编译、本地安装ubuntu180.04

一、zeromq的编译安装 1&#xff09;ubuntu下命令 apt-get install libzmq3-dev不推荐这种方式&#xff0c;因为很可能安装的版本并不是最新的&#xff1b; 2&#xff09;自己编译安装&#xff08;推荐&#xff09; 地址&#xff1a;https://github.com/zeromq/libzmq/relea…

设计模式--装饰者模式

文章目录前言一、未使用设计模式二、装饰者模式1.定义2.角色三、应用场景四、优缺点优缺前言 晓子&#xff08;咖啡店员&#xff09;&#xff0c;来一杯美式&#xff0c;加点威士忌和砂糖。 抱歉啊&#xff0c;猫。收银系统还没有你说的组合&#xff0c;要不换一个&#x1f60…