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");elsedb = QSqlDatabase::addDatabase("QSQLITE");//检测已连接的方式 - 自定义连接名/*if(QSqlDatabase::contains("mysql_connection"))db = QSqlDatabase::database("mysql_connection");elsedb = QSqlDatabase::addDatabase("QSQLITE","mysql_connection");*///设置数据库路径,不存在则创建db.setDatabaseName("sqltest.db");//db.setUserName("gongjianbo");  //SQLite不需要用户名和密码//db.setPassword("qq654344883");//打开数据库if(db.open()){qDebug()<<"open success";//关闭数据库db.close();}}

上面的代码中,先是创建了一个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;"语句,可以提升效率,不过若不是临时数据库不建议此操作。

其他效率提升见参考博客。

(2021-1-24补充)多线程操作:

(对如多线程建立连接,参照 https://gongjianbo1992.blog.csdn.net/article/details/105518870 )

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

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

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

6.工具

两个轻量的 SQLite 可视化工具,都提供了免安装版本:

SQLite Studio(可以在Tool->Config->Look设置简体中文但是新版有些地方没翻译,打开db后别的程序也可以正常操作该db):https://sqlitestudio.pl/

DB Browser For SQLite(有中文翻译,但是打开db后别程序的无法操作该db):http://www.sqlitebrowser.org/dl/

7.参考

文档:https://doc.qt.io/qt-5/qsqldatabase.html

博客:https://www.cnblogs.com/xia-weiwen/archive/2017/05/04/6806709.html

博客:http://blog.sina.com.cn/s/blog_a6fb6cc90101gx30.html

SQLite教程:http://www.runoob.com/sqlite/sqlite-tutorial.html

SQLite优化:https://www.cnblogs.com/zzyyxxjc/p/7495279.html

SQLite优化:https://www.cnblogs.com/huozhong/p/5973938.html

Qt中操作SQLite数据库相关推荐

  1. 在Qt中操作MySQL数据库

    目录 一.安装驱动 (1)安装 (2)验证驱动是否安装成功 二.使用MySQL数据库 (1)单语句执行 (2)多语句执行 (3)批处理操作 方式一:addBindValue() 方式二:bindVal ...

  2. python ——操作sqlite 数据库

    活动地址:CSDN21天学习挑战赛 目录 一,什么是sqlite数据库 1.1 sqlite数据库的功能特性 2,python操作sqlite 2.1 python sqlite3 模块 2.2 创建 ...

  3. Qt操作SQLite数据库的三种方式

    Qt访问Sqlite数据库的三种方式(即使用三种类库去访问),分别为QSqlQuery.QSqlQueryModel.QSqlTableModel,对于这三种类库,可看为一个比一个上层,也就是封装的更 ...

  4. Android中实现SQLite数据库CRUD操作的两种方式

    Android中实现SQLite数据库CRUD操作的两种方式 SQLite是一款轻量级的关系型数据库,具有运行速度.占用资源少的特点.通常只需要几百KB的内存就够了,因此特别适合在移动设备上使用.SQ ...

  5. Electron中使用sql.js操作SQLite数据库

    推荐sql.js--一款纯js的sqlite工具. 一.关于sql.js sql.js(https://github.com/kripken/sql.js)通过使用Emscripten编译SQLite ...

  6. 在 Android 应用程序中使用 SQLite 数据库以及怎么用

    part one : android SQLite 简单介绍 SQLite 介绍 SQLite 一个非常流行的嵌入式数据库.它支持 SQL 语言,而且仅仅利用非常少的内存就有非常好的性能.此外它还是开 ...

  7. Android中关于SQLite数据库的一些知识

    使用嵌入式关系型SQLite数据库存储数据 在Android平台上,集成了一个嵌入式关系型数据库-SQLite,SQLite3支持 NULL.INTEGER.REAL(浮点数字).TEXT(字符串文本 ...

  8. python读数据库的通信协议是,Python操作SQLite数据库过程解析

    SQLite是一款轻型的数据库,是遵守ACID的关系型数据库管理系统. 不像常见的客户-服务器范例,SQLite引擎不是个程序与之通信的独立进程,而是连接到程序中成为它的一个主要部分.所以主要的通信协 ...

  9. 使用SQLite数据库存储数据(1)-操作SQLite数据库

    在使用SQLite API函数如有疑问,可以参考官方函数文档: http://www.sqlite.org/c3ref/funclist.html 操作SQLite数据库 SQLite数据库是文件数据 ...

最新文章

  1. Visual C++ 对话框增加菜单栏
  2. 卍解,开放基础架构的力量--9月26日免费大型讲座预告
  3. python字符计数怎样去除空格_去除python中的字符串空格的简单方法
  4. [Angularjs]angular ng-repeat与js特效加载先后导致的问题
  5. 什么是作用域链(源码解析)
  6. 深度学习自学(三十七):基于用户自定义要求3D房间自动设计研究
  7. 求四科平均成绩c语言,c语言实验报告评语大全
  8. Who's in the Middle - poj 2388 (快速排序寻找中位数)
  9. 【每天学点心理学第七期】人性定理:人都是以服务于他自己为目的的!
  10. java实行图片上写字
  11. android 跑马灯速度,自定义TextView跑马灯效果可控制启动/停止/速度/焦点
  12. stm32f7699遇到的犯二问题
  13. 什么是python语言的解释性?
  14. 与计算机学男生谈恋爱,和什么专业男生谈恋爱比较惨?
  15. js 万年历农历转阳历 方法_JavaScript实现公历转农历功能示例
  16. 为什么重大疾病保险最好要选择保障终身?
  17. paperpass论文查重
  18. 【大厂算法系列】学数据结构与算法有用吗?时间与空间复杂度的定义与计算
  19. 刘德华--3无线五年之约
  20. win7时间总是不对怎么办?

热门文章

  1. 西安交通大学915考研--编程题Java代码踩坑(2020年真题)
  2. 【NYOJ】[845]无主之地1
  3. 用excel对2000年-2015年游戏行业分析
  4. 如何进入docker 使用root用户的方式
  5. lattice fpga ddr3 读写控制
  6. 【项目记录】-上门洗车-汽车服务
  7. eslint报“Extra semicolon“错误的解决
  8. 【AGV——第1篇】AGV导航方式
  9. 微信小程序video组件调用腾讯视频的解析
  10. 求n的阶乘并显示过程