常用数据库之sqlite的使用

news2024/11/24 19:28:14

2.1 介绍

  sqlite为关系型数据库,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它的设计目标是嵌入式的,而且已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了.

  SQLite 是一个软件库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是在世界上最广泛部署的 SQL 数据库引擎。SQLite 源代码不受版权限制。

2.2 优缺点

优点:

    1>sqlite占用的内存和cpu资源较少
    2>源代码开源,完全免费
    3>检索速度上十几兆、几十兆的数据库sqlite很快,但是上G的时候最慢
    4>管理简单,几乎无需管理。灵巧、快速和可靠性高
    5>功能简约,小型化,追求最大磁盘效率

缺点:

    1>不支持多用户多线程同时读写数据库
    2>数据库同一时间仅仅同意一个写操作。因此吞吐量有限。

2.3 在windows安装

    1>下载 sqlite-tools-win32-.zip 和 sqlite-dll-win32-.zip 压缩文件
    2>创建文件夹 C:\sqlite,并在此文件夹下解压上面两个压缩文件,将得到 sqlite3.def、sqlite3.dll 和 sqlite3.exe 文件
    3>添加 C:\sqlite 到 PATH 环境变量,最后在命令提示符下,使用 sqlite3 命令

2.4 在qt上的使用

database.h

#ifndef DATABASE_H
#define DATABASE_H

#include <QSqlQuery>
#include <QSqlRecord>
#include <QSqlField>
#include <QSqlDriver>
#include <QSqlError>
#include <QSqlDatabase>
#include <QMutex>

typedef struct db_user
{
    QString sUsername;
    QString sPassword;
    int nAuth;
} DB_USER_t;


typedef void (*db_callback)(void*pUser, void*pData);
typedef void (*db_callback2)(void*pUser1, void*pUser2, void*pData);


class Database : public QObject
{
    Q_OBJECT
public:
    virtual ~Database();

    static Database& getInstance();
    int db_init(const QString& sDbPath);
    int db_run_cmd(QString& sql);
    int db_query_cmd(QString& sql);

    //User 增删改查
    int db_user_delete(QString sUsername);
    int db_user_get_all(int* pUserNum ,DB_USER_t* user);
    int db_user_get_byname(QString &username, DB_USER_t* user);
    int db_user_add(DB_USER_t* user);
    int db_user_modify_pwd(DB_USER_t* user);

private:
    Database(QObject *parent = NULL);
    QMutex      *m_dbLock;
    QSqlDatabase m_db;
    QString      m_dbcon;
    QSqlQuery   *m_dbQuery;
    bool         m_bLock;

signals:
    void sig_databaseLock();
};

#endif // DATABASE_H

database.cpp

#include "database.h"
#include <QCoreApplication>
#include <QObject>
#include <QMutex>
#include <QMutexLocker>
#include <QDebug>
#include <QDateTime>
#include "commondef.h"

static int g_nCon = 0;

#define DB_NAME         "db/mydb.db"
#define DB_TYPE         "QSQLITE"
#define DB_TBL_USEr     "User"


#define DB_CREATE_TBL_USER   \
    "CREATE TABLE [User](\
        [username] VARCHAR(32) NOT NULL, \
        [password] VARCHAR(32) NOT NULL, \
        [auth] INTEGER NOT NULL DEFAULT 0);"

Database::Database(QObject *parent)
    : QObject(parent)
{
    this->setObjectName("MyDB");
    QString sDbPath = QString("%1/%2").arg(QCoreApplication::applicationDirPath()).arg(DB_NAME);
    MY_DEBUG << "sDbPath:" << sDbPath;
    db_init(sDbPath);
}

Database &Database::getInstance()
{
    static Database s_db;
    return s_db;
}

int Database::db_init(const QString& sDbPath)
{
    m_dbLock = new QMutex(QMutex::Recursive);
    QMutexLocker mutexlock(m_dbLock);
    m_bLock = false;

    // 1. create connect.
    m_dbcon = QString("DatabaseCon%1").arg(g_nCon++);
    m_db = QSqlDatabase::addDatabase(DB_TYPE, m_dbcon);
    m_db.setDatabaseName(sDbPath);
    if(!m_db.open())
    {
        MY_DEBUG << "Db open failed!!!";
        return -1;
    }
    // 2. check if exsist table.
    m_dbQuery = new QSqlQuery(m_db);
    m_dbQuery->clear();
    bool isTableExist = m_dbQuery->exec(
                QString("select count(*) from sqlite_master where type='table' and name='%1'").\
                arg(DB_TBL_USEr));
    m_dbQuery->next();
    if(!isTableExist || m_dbQuery->value(0).toInt() == 0)
    {
        m_dbQuery->exec(DB_CREATE_TBL_USER);
        // 1. add default users.
        DB_USER_t stUser = {"admin", "123456", 0};
        return db_user_add(&stUser);
    }
    return 0;
}

Database::~Database()
{
    m_dbLock->lock();
    if(m_db.isOpen())
    {
        m_db.close();
    }
    QSqlDatabase::removeDatabase(m_dbcon);
    delete m_dbQuery;
    m_dbLock->unlock();
    delete m_dbLock;
}

int Database::db_run_cmd(QString &sql)
{
    QMutexLocker mutexlock(m_dbLock);

    // 1. check valid.
    if(!m_db.isOpen() || !m_db.isValid())
    {
        MY_DEBUG << "db is not valid";
        return -1;
    }

    // 2. clear old query.
    m_dbQuery->clear();

    // 3. run command.
    if(!m_dbQuery->exec(sql))
    {
        MY_DEBUG << "run sql:" << sql;
        MY_DEBUG << "m_dbQuery->exec fail: " << m_dbQuery->lastError();
        if(m_bLock == false && m_dbQuery->lastError().text().contains("locked"))
        {
            emit sig_databaseLock();
            m_bLock = true;
        }
        return -1;
    }
    return 0;
}

int Database::db_query_cmd(QString &sql)
{
    // 1. check valid.
    if(!m_db.isOpen() || !m_db.isValid())
    {
        MY_DEBUG << "db is not valid";
        return -1;
    }

    // 2. clear old query.
    m_dbQuery->clear();

    // 3. run command.
    if(!m_dbQuery->exec(sql))
    {
        MY_DEBUG << "run sql:" << sql;
        MY_DEBUG << "m_dbQuery->exec fail: " << m_dbQuery->lastError();
        return -1;
    }
    return 0;
}

//User
int Database::db_user_delete(QString sUsername)
{
    QString sql = QString("delete from User where username = '%1'").arg(sUsername);
    return db_run_cmd(sql);
}

int Database::db_user_get_all(int* pUserNum ,DB_USER_t* user)
{
    QMutexLocker mutexlock(m_dbLock);

    // 1. query exec.
    QString sql = QString("select username,password,auth from User");
    if(db_query_cmd(sql))
    {
        MY_DEBUG << "DBERR: " << __FUNCTION__ << __LINE__;
        return -1;
    }

    // 2. get all data.
    int i = 0;
    while(m_dbQuery->next() && i < MAX_USER_NUM)
    {
        user[i].sUsername = m_dbQuery->value(0).toString();
        user[i].sPassword = m_dbQuery->value(1).toString();
        user[i].nAuth = m_dbQuery->value(2).toInt();
        i++;
    }
    if(i == 0)
    {
        MY_DEBUG << "DBERR: " << __FUNCTION__ << __LINE__;
        return -1;
    }
    *pUserNum = i;
    return 0;
}

int Database::db_user_get_byname(QString &username, DB_USER_t *user)
{
    QMutexLocker mutexlock(m_dbLock);

    // 1. query exec.
    QString sql = QString("select username,password,auth from User where username='%1'").arg(username);
    if(db_query_cmd(sql))
    {
        MY_DEBUG << " db_query_cmd failed";
        return -1;
    }

    // 2. get user data.
    if(m_dbQuery->next())
    {
        user->sUsername = username;
        user->sPassword = m_dbQuery->value(1).toString();
        user->nAuth = m_dbQuery->value(2).toInt();
        return 0;
    }

    return -1;
}

int Database::db_user_add(DB_USER_t *user)
{
    QString sql = QString("insert into User(username, password, auth) values('%1', '%2', %3)").\
            arg(user->sUsername).arg(user->sPassword).arg(user->nAuth);
    return db_run_cmd(sql);
}

int Database::db_user_modify_pwd(DB_USER_t *user)
{
    QString sql = QString("UPDATE User set password = '%1', auth = %2 where username='%3'").\
            arg(user->sPassword).arg(user->nAuth).arg(user->sUsername);
    return db_run_cmd(sql);
}

main.cpp

#include <QCoreApplication>
#include "database.h"
#include "commondef.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    //增
    DB_USER_t stUser1 = {"test1", "test1_123456", 0};
    Database::getInstance().db_user_add(&stUser1);


    //查
    MY_DEBUG << "##############1##################";
    int nUserNum;
    DB_USER_t db_user[MAX_USER_NUM];
    Database::getInstance().db_user_get_all(&nUserNum, db_user);

    MY_DEBUG << "nUserNum:" << nUserNum;
    for(int i = 0; i < nUserNum; i++)
    {
        MY_DEBUG << "i:" << i << ", db_user->sUsername:" << db_user[i].sUsername << ", db_user->sPassword:" << db_user[i].sPassword << ", db_user->nAuth:" << db_user[i].nAuth;
    }

    //改
    DB_USER_t stUser2 = {"test1", "test1_654321", 0};
    Database::getInstance().db_user_modify_pwd(&stUser2);

    //查
    MY_DEBUG << "##############2##################";
    DB_USER_t stUser3;
    QString sUsername = "test1";
    Database::getInstance().db_user_get_byname(sUsername, &stUser3);
    MY_DEBUG << "stUser3.sUsername:" << stUser3.sUsername << ", stUser3.sPassword:" << stUser3.sPassword << ", stUser3.nAuth:" << stUser3.nAuth;

    //删
    Database::getInstance().db_user_delete("test1");

    //查
    MY_DEBUG << "##############3##################";
    int nUserNum2;
    DB_USER_t db_user2[MAX_USER_NUM];
    Database::getInstance().db_user_get_all(&nUserNum2, db_user2);

    for(int i = 0; i < nUserNum2; i++)
    {
        MY_DEBUG << "i:" << i << ", db_user2->sUsername:" << db_user2[i].sUsername << ", db_user2->sPassword:" << db_user2[i].sPassword << ", db_user2->nAuth:" << db_user2[i].nAuth;
    }
    return a.exec();

在这里插入图片描述

2.5 qt-demo下载

下载链接:https://download.csdn.net/download/linyibin_123/86341593

2.6 sqlite的具体学习

菜鸟教程:https://www.runoob.com/sqlite/sqlite-intro.html

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

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

相关文章

反序列化__wakeup

简介 __wakeup()&#xff0c;执行unserialize()时&#xff0c;先会调用这个函数。 <?php class c1 {private $argv;private $method;function __construct($argv,$method){$this->argv$argv;$this->method$method;}public function f1(){ech…

BUG系列路径规划算法原理介绍(六)——BugFlood算法

本系列文章主要对Bug类路径规划算法的原理进行介绍&#xff0c;在本系列的第一篇文章中按照时间顺序梳理了自1986年至2018年Bug类路径规划算法的发展&#xff0c;整理了13种BUG系列中的典型算法&#xff0c;从本系列的第二篇文章开始依次详细介绍了其中具有代表性的BUG1、BUG2、…

KubeSphere开启DevOps 功能教程

基于 Jenkins 的 KubeSphere DevOps 系统是专为 Kubernetes 中的 CI/CD 工作流设计的&#xff0c;它提供了一站式的解决方案&#xff0c;帮助开发和运维团队用非常简单的方式构建、测试和发布应用到 Kubernetes。它还具有插件管理、Binary-to-Image (B2I)、Source-to-Image (S2…

MySQL遵循最左前缀匹配原则!面试官:回去等通知吧

我们都知道&#xff0c;MySQL的Innodb引擎中&#xff0c;索引是通过B树来实现的。不管是普通索引还是联合索引&#xff0c;都需要构造一个B树的索引结构。 那么&#xff0c;我们都知道普通索引的存储结构中在B树的每个非节点上记录的索引的值&#xff0c;而这棵B树的叶子节点上…

Markdown官方教程(六)

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…

Spring Boot 创建项目 / 目录介绍 / 配置文件

目录 Spring Boot项目创建 一、通过IDEA来创建Spring Boot项目 二、通过网页版创建Spring Boot项目 Spring Boot项目目录介绍 Spring Boot项目创建 一、通过IDEA来创建Spring Boot项目 社区版IDEA需要先安装 Spring Assistant 插件。 1. 创建新项目&#xff0c;选择Sprin…

2022最后一个月,我们该如何学Java​?

2022最后一个月&#xff0c;我们该如何学Java&#xff1f; 互联网的快速发展和激烈竞争&#xff0c;在世界编程语言排行榜中&#xff0c;Java位列前三&#xff0c;占全球编程市场份额的12%左右,各大公司对Java工程师的需求量都很大&#xff0c;要求也越来越高&#xff0c;优秀…

Gradle学习第一篇——自定义Gradle插件

纸上得来终觉浅&#xff0c;绝知此事要躬行。 自定义Gradle插件有三种方法&#xff0c;各有优劣处&#xff0c;同类博客文章很多但是有的语法已经过时了&#xff0c;笔者运行环境 Android Studio Dolphin && gradle-7.4-bin 文章目录第一种 build script (单文件生效)第…

Linux目录操作

一、常用权限操作 权限操作实战 1、创建文件&#xff0c;设置其用户组 root用户创建新文件love.txt 命令&#xff1a;echo I Love you > love.txt 查看文件love.txt的用户及用户组 将其用户组改为lzy用户组 命令&#xff1a;chgrp lzy love.txt 查看文件love.txt的用…

System Verilog断言

简介 断言通常被称为序列监视器或者序列检验器&#xff0c;是对设计应当如何执行特定行为的描述&#xff0c;是一种嵌入设计检查。如果检查的属性&#xff08;property&#xff09;不是我们期望的表现&#xff0c;那么在我们期望事件序列的故障上会产生警告或者错误提示。 断言…

SpringMVC:整合SSM框架

一、大致框架 1.建立数据库&#xff0c;并导入数据 create database cjgl; create table books( bookID int(10) not null auto_increment comment 书id, bookName varchar(100) not null comment 书名, bookCounts int(11) not null comment 数量, detail varchar(200) no…

C. Planar Reflections

题目如下&#xff1a; 思路 or 题解 我们可以通过图解发现&#xff1a;可以递推找到答案了 我们约定&#xff1a;dp[i][j]dp[i][j]dp[i][j] 第 iii 个板, 衰变年龄为jjj 的答案是 dp[i][j]dp[i][j]dp[i][j] 我们通过图解找到转移方程&#xff1a; dp[i][j]dp[i−1][j]dp[n−i]…

[附源码]Python计算机毕业设计Django时间管理软件app

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

数据结构【红黑树模拟实现】

目录 红黑树&#xff1a;基于AVL树改进 红黑树的性质 红黑树基本结构 insert基本结构 新增节点的默认颜色为红色 节点性质总结 情况一: cur为红&#xff0c;p为红&#xff0c;g为黑&#xff0c;u存在且为红 情况二: cur为红&#xff0c;p为红&#xff0c;g为黑&#xf…

基于web的电子图书管理系统

目  录 中文摘要&#xff08;关键词&#xff09; 1 英文摘要&#xff08;关键词&#xff09; 1 前 言 2 1概述 3 1.1系统研究背景 3 1.2系统研究意义 3 2 需求分析 4 2.1可行性分析 4 2.2功能需求分析 4 2.3非功能需求分析 5 3系统分析 6 3.1系统业务流程分析 6 3.2系统数据…

web前端课程设计 HTML+CSS+JavaScript旅游风景云南城市网页设计与实现 web前端课程设计代码 web课程设计 HTML网页制作代码

&#x1f468;‍&#x1f393;静态网站的编写主要是用 HTML DⅣV CSSJS等来完成页面的排版设计&#x1f469;‍&#x1f393;&#xff0c;一般的网页作业需要融入以下知识点&#xff1a;div布局、浮动定位、高级css、表格、表单及验证、js轮播图、音频视频Fash的应用、uli、下拉…

狂神说多线程学习笔记

一、线程简介 1、多任务 现实中太多这样同时做多件事情的例子了&#xff0c;看起来是多个任务都在做&#xff0c;其实本质上我们的大脑在同一时间依旧只做了一件事情。 2、多线程 原来是一条路&#xff0c;慢慢因为车太多了&#xff0c;道路阻塞&#xff0c;效率极低。为了提…

【信管2.6】项目可研(二)详细可行性研究

项目可研&#xff08;二&#xff09;详细可行性研究在实际的整个项目可研的过程中&#xff0c;机会研究和初步可行性研究有可能不会出现&#xff0c;但详细可行性研究这个步骤是不可缺少的。比如说一些升级改造的项目可能需要初步和详细的可行性研究&#xff0c;而一些小项目可…

阿里P8大牛带你深入理解SpringCloud微服务构建文档

前言 蓦然回首自己做开发已经十年了&#xff0c;这十年中我获得了很多&#xff0c;技术能力、培训、出国、大公司的经历&#xff0c;还有很多很好的朋友。但再仔细一想&#xff0c;这十年中我至少浪费了五年时间&#xff0c;这五年可以足够让自己成长为一个优秀的程序员&#…

嵌入式开发学习之--RCC(下)

文章目录前言一、使用HSE二、使用HSI三、代码编写总结前言 这一篇记录一下时钟的具体实验。 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、使用HSE 一般情况下&#xff0c;我们都是使用 HSE&#xff0c;然后 HSE 经过 PLL 倍频之后作为系统时钟…