嵌入式数据库SQLite 3配置使用详细笔记教程

0、惨痛教训

        随着管理开发的项目体积越来越庞大,产品系统涉及的数据量也越来越多,并且伴随着项目不久就要交付给甲方了。如果项目的数据信息没有被妥善管理,后期设备的运行状态、操作状况等数据流信息不能被溯源,当出现了一些特殊意外时,就会导致对于故障信息不能迅速准确的追踪,甚至会被甩锅、推卸责任,白白当了冤大头。因此对于嵌入式项目中,其产品运行时的数据库建立非常有必要,且是迫在眉睫!!!

        目前常用的数据库系统有:MySQL、PostgreSQL、Oracle Database、Microsoft SQL Server、SQLite等。在嵌入式项目中,前面几个数据库显然是不合适的,而SQLite是一个轻量级的数据库管理系统,它包含在一个C库中,提供了零配置、无服务器、事务性的SQL数据库引擎。所以SQLite的特点使其非常适合嵌入式系统、移动设备、小型项目或者作为应用程序的本地数据库使用。本文选用了嵌入式数据库SQLite3进行配置和讲解。

1、Sqlite3环境配置

(1)、下载安装SQLite库

根据目标系统平台,下载sqlite源码,或下载官方提供的已经编译好的库。本文目标平台是Windows11 64位平台,进入SQLite Download Page的主页,选择需要的库版本(Windows)。

下载的压缩包一共有如下所示的三个:

sqlite-dll-win-x64-3450300.zip

sqlite-dll-win-x86-3450300.zip

sqlite-tools-win-x64-3450300.zip

(2)、解压下载的文件

        本文中将对应的Sqlite库文件解压到了,C:\Program Files\sqlite路径下。

(3)、添加库路径到环境变量

        根据下图所示的步骤,进入系统属性-->环境变量-->系统变量-->编辑环境变量,将路径加入到环境变量中。

(4)、检查数据库安装状态

        打开Windows的命令行,输入sqlite3,有类似如下的数据信息说明库安装成功,后续只需在程序代码中,将库加入到工程代码中即可。

(5)、SQLiteStudio工具

        如果有可视化分析数据需求、推荐使用下载:SQLiteStudioicon-default.png?t=N7T8https://sqlitestudio.pl/

2、SQLite3基础

        SQL(Structured Query Language)是一种结构化查询语言,SQL 是一种专门用来与数据库通信的语言。

        不同的数据库管理系统在其实践过程中都对 SOL 规范作了某些改编和扩充。故不同数据库管理系统之间的 SOL语言不能完全相互通用。

        以下是SQLite的一些关键特点:

  • 零配置: SQLite不需要安装或者管理服务器进程。启动一个使用SQLite的应用程序时,数据库文件会自动创建(如果尚不存在),并且直接通过程序访问。
  • 轻量级: SQLite的代码量小,资源消耗少,对硬件要求很低。这使得它非常适合资源有限的环境,如手机、平板电脑或微型设备。
  • 跨平台: SQLite兼容几乎所有主流的操作系统,包括Windows、Linux、Unix、Android、iOS等。
  • 服务器less: 由于SQLite是嵌入式的,没有单独运行的数据库服务器进程,数据直接存储在文件中。这简化了部署和维护过程。
  • 事务处理: SQLite支持ACID(原子性、一致性、隔离性、持久性)事务,确保数据的完整性。
  • SQL标准兼容: 虽然SQLite有自己的SQL方言,但它大体上遵循ANSI SQL标准,支持大多数标准SQL语句。
  • 单一文件存储: SQLite数据库完全存储在一个磁盘文件中,这使得备份和迁移数据库变得非常简单,只需复制该文件即可。
  • 动态类型: SQLite具有弱类型特性,允许更灵活的数据存储,但也可能需要开发者更加注意数据类型的处理。
  • 广泛使用: SQLite被许多应用程序和操作系统采用,包括浏览器(如Firefox)、操作系统组件、手机应用等,是世界上最广泛部署的数据库引擎之一。

        有个重要的点值得注意,SQLite 是不区分大小写的,但也有一些命令是大小写敏感的,比如 GLOB 和 glob 在 SQLite 的语句中有不同的含义。一般数据采用固定的静态数据类型,而 SOLite 采用的是动态数据类型,会根据存入值自动判断。

SQLite 存储类:SOLite 具有以下五种基本数据类型

(1)integer:带符号的整型(最多64位)。

(2)real:8字节表示的浮点类型。

(3)text:字符类型,支持多种编码(如 UTF-8、UTF-16),大小无限制。

(4)blob:任意类型的数据,大小无限制。 BLOB(binary large obiect)二进制大对象,使用二进制保存数据。

(5)null:表示空值

SQLite 亲和类型(Affinity)及类型名称

下表列出了当创建 SQLite3 表时可使用的各种数据类型名称,同时也显示了相应的亲和类型

数据类型

亲和类型

  • INT
  • INTEGER
  • TINYINT
  • SMALLINT
  • MEDIUMINT
  • BIGINT
  • UNSIGNED BIG INT
  • INT2
  • INT8

INTEGER

  • CHARACTER(20)
  • VARCHAR(255)
  • VARYING CHARACTER(255)
  • NCHAR(55)
  • NATIVE CHARACTER(70)
  • NVARCHAR(100)
  • TEXT
  • CLOB

TEXT

  • BLOB
  • 未指定类型

BLOB

  • REAL
  • DOUBLE
  • DOUBLE PRECISION
  • FLOAT

REAL

  • NUMERIC
  • DECIMAL(10,5)
  • BOOLEAN
  • DATE
  • DATETIME

NUMERIC

SQLite 语句:所有的 SQLite 语句可以以任何关键字开始,如 SELECT、INSERT、UPDATE、DELETE、ALTER、DROP 等,所有的语句以分号 ; 结束。

3、SQLite3基本语法

(1)、创建数据库

//打开数据库,如不存在则会创建数据库
int ret = sqlite3_open("project_data.db", &db);
if( ret )
{fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));exit(-1);
}
fprintf(stderr, "Opened database successfully\n");

(2)、创建表

//CREATE TABLE 告诉数据库系统创建一个新表的关键字。CREATE TABLE 语句后跟着表的唯一的名称或标识。
CREATE TABLE database_name.table_name(column1 datatype  PRIMARY KEY(one or more columns),column2 datatype,column3 datatype,.....columnN datatype,
);char table_name[200] = {0};
char *err_msg = NULL;
snprintf(table_name, sizeof(table_name), "create table if not exists camera(time_stamp integer primary key, action text, x integer, y integer, z integer, vx integer, vy integer, vz integer, time integer);");
int ret = sqlite3_exec(db, table_name, NULL, NULL, &err_msg);
if(ret){fprintf(stderr, "create table err:%s\n", err_msg);return -1;
}
fprintf(stderr, "create table successfully\n");

(3)、删除表

//SQLite 的 DROP TABLE 语句用来删除表定义及其所有相关数据、索引、触发器、约束和该表的权限规范。
//DROP TABLE 语句的基本语法如下。
DROP TABLE database_name.table_name;char table_name[200] = {0};
char *err_msg = NULL;
snprintf(table_name, sizeof(table_name), "DROP TABLE database_name.table_name;");
int ret = sqlite3_exec(db, table_name, NULL, NULL, &err_msg);
if(ret){fprintf(stderr, "delete table err:%s\n", err_msg);return -1;
}
fprintf(stderr, "delete table successfully\n");

(4)、插入数据

INSERT INTO 语句有两种基本语法,如下所示:
INSERT INTO TABLE_NAME [(column1, column2, column3,...columnN)]  VALUES (value1, value2, value3,...valueN);//在这里,column1, column2,...columnN 是要插入数据的表中的列的名称
或
INSERT INTO TABLE_NAME VALUES (value1,value2,value3,...valueN);
//确保值的顺序与列在表中的顺序一致。char table_value[200] = {0};
int ret = 0;
char *err_msg = NULL;
snprintf(table_value, sizeof(table_value),"insert into camera values(%lld, '%c', %d, %d, %d, %d, %d, %d, %d);", get_current_timestamp_ms(), action, x, y, z, vx, vy, vz, time);
ret = sqlite3_exec(db, table_value, NULL, NULL, &err_msg);
if(ret)
{fprintf(stderr, "insert value to table err:%s\n", err_msg);return -1;
}
fprintf(stderr, "insert value to table successfully\n");

(5)、查询数据

//SQLite 的 SELECT 语句用于从 SQLite 数据库表中获取数据,以结果表的形式返回数据。这些结果表也被称为结果集。
//SQLite 的 SELECT 语句的基本语法如下:
SELECT column1, column2, columnN FROM table_name;//在这里,column1, column2...是表的字段,他们的值即是您要获取的。
SELECT * FROM table_name;    //获取所有可用的字段char *err_msg = NULL;
sprintf(sql, "select * from table_value;");
ret = sqlite3_exec(db, sql, NULL, NULL, &err_msg);   //执行 SQL 命令的快捷方式
if(ret)
{fprintf(stderr, "Can't select sqlite value: %s\n", sqlite3_errmsg(db));return -1;
}

(6)、删除数据

//SQLite 的 DELETE 查询用于删除表中已有的记录。可以使用带有 WHERE 子句的 DELETE 查询来删除选定行,否则所有的记录都会被删除。
//带有 WHERE 子句的 DELETE 查询的基本语法如下:
DELETE FROM table_name
WHERE [condition];
//可以使用 AND 或 OR 运算符来结合 N 个数量的条件。char *err_msg = NULL;
sprintf(sql, "DELETE FROM camera WHERE time_stamp = 123456789;");
ret = sqlite3_exec(db, sql, NULL, NULL, &err_msg);   //执行 SQL 命令的快捷方式
if(ret)
{fprintf(stderr, "Can't DELETE sqlite data: %s\n", sqlite3_errmsg(db));return -1;
}

(7)、修改数据

//SQLite 的 UPDATE 查询用于修改表中已有的记录。可以使用带有 WHERE 子句的 UPDATE 查询来更新选定行,否则所有的行都会被更新。
//带有 WHERE 子句的 UPDATE 查询的基本语法如下:
UPDATE table_name
SET column1 = value1, column2 = value2...., columnN = valueN
WHERE [condition];char *err_msg = NULL;
sprintf(sql, "UPDATE camera SET action = 't' WHERE time_stamp = 123456789;");
ret = sqlite3_exec(db, sql, NULL, NULL, &err_msg);   //执行 SQL 命令的快捷方式
if(ret)
{fprintf(stderr, "Can't DELETE sqlite data: %s\n", sqlite3_errmsg(db));return -1;
}

4、SQLite3代码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sqlite3.h>int database_init();
int write_motor_info_to_database(sqlite3 *db, int motor_id, double target_pos, double real_pos, double real_speed, double real_current);
int write_camera_info_to_database(sqlite3 *db, char action, int x, int y, int z, int vx, int vy, int vz, int time);
long long get_current_timestamp_ms(void); int main(void)
{printf("sqlite3 database test!\n");    database_init();return 0;
}/*** @brief  数据库初始化* @param  NONE* @retval 成功返回0, 失败返回-1*/
int database_init(void)  
{int ret = -1;sqlite3 *db;char *err_msg = NULL;char database_name[128] = {0};//获取当前时间struct tm t; time_t now;time(&now);localtime_s(&t, &now);snprintf(database_name, sizeof(database_name),"%02d%02d%02d.db", t.tm_year + 1900, t.tm_mon + 1, t.tm_mday);printf("date:%s\n", database_name);//打开数据库ret = sqlite3_open(database_name, &db);if( ret ){fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));return -1;}fprintf(stderr, "Opened database successfully\n");char table_name[200] = {0};//时间戳 目标位置 实际位置 实际速度 实际电流//create table if not exists motor0 (time_stamp integer primary key, target_pos real, real_pos real, real_speed real, real_current, real);for(int motor_id = 0; motor_id < 6; motor_id++){snprintf(table_name, sizeof(table_name),"create table if not exists motor%d (time_stamp integer primary key, target_pos real, real_pos real, real_speed real, real_current real);", motor_id);ret = sqlite3_exec(db, table_name, NULL, NULL, &err_msg);if(ret){fprintf(stderr, "create table err:%s\n", err_msg);return -1;}fprintf(stderr, "create table successfully\n");}memset(table_name, 0, sizeof(table_name));snprintf(table_name, sizeof(table_name), "create table if not exists camera(time_stamp integer primary key, action text, x integer, y integer, z integer, vx integer, vy integer, vz integer, time integer);");ret = sqlite3_exec(db, table_name, NULL, NULL, &err_msg);if(ret){fprintf(stderr, "create table err:%s\n", err_msg);return -1;}fprintf(stderr, "create table successfully\n");write_motor_info_to_database(db, 0, 90.0, 87.2, 5.0, 0.85);write_motor_info_to_database(db, 1, 90.0, 87.2, 5.0, 0.85);write_motor_info_to_database(db, 2, 90.0, 87.2, 5.0, 0.85);write_motor_info_to_database(db, 3, 90.0, 87.2, 5.0, 0.85);write_motor_info_to_database(db, 4, 90.0, 87.2, 5.0, 0.85);write_motor_info_to_database(db, 5, 90.0, 87.2, 5.0, 0.85);write_camera_info_to_database(db, 't', 100,200,150,160,130,110,1000);return 0;
}/*** @brief  写入电机数据到数据库中* @param  db:数据库文件描述符* @param  target_pos:目标位置* @param  real_pos:实际位置* @param  real_speed:实际速度* @param  real_current:实际电流* @retval 写入成功返回0,失败-1*/
int write_motor_info_to_database(sqlite3 *db, int motor_id, double target_pos, double real_pos, double real_speed, double real_current)
{char table_value[200] = {0};int ret = 0;char *err_msg = NULL;//insert into motor0 values(1798345, 90.0, 88.66, 45.1, 0.97);snprintf(table_value, sizeof(table_value),"insert into motor%d values(%lld, %.2f, %.2f, %.2f, %.2f);", motor_id, get_current_timestamp_ms(), target_pos, real_pos, real_speed, real_current);ret = sqlite3_exec(db, table_value, NULL, NULL, &err_msg);if(ret){fprintf(stderr, "insert value to table err:%s\n", err_msg);return -1;}fprintf(stderr, "insert value to table successfully\n");return 0;
}/*** @brief  写入相机数据到数据库中* @param  db:数据库文件描述符* @param  action:动作* @param  x:* @param  y:* @param  z:* @param  vx:* @param  vy:* @param  vz:* @retval 写入成功返回0,失败-1*/
int write_camera_info_to_database(sqlite3 *db, char action, int x, int y, int z, int vx, int vy, int vz, int time)
{char table_value[200] = {0};int ret = 0;char *err_msg = NULL;//insert into motor0 values(1798345, 90.0, 88.66, 45.1, 0.97);snprintf(table_value, sizeof(table_value),"insert into camera values(%lld, '%c', %d, %d, %d, %d, %d, %d, %d);", get_current_timestamp_ms(), action, x, y, z, vx, vy, vz, time);ret = sqlite3_exec(db, table_value, NULL, NULL, &err_msg);if(ret){fprintf(stderr, "insert value to table err:%s\n", err_msg);return -1;}fprintf(stderr, "insert value to table successfully\n");return 0;
}/*** @brief  获取毫秒级时间戳* @param  NONE* @retval 成功返回时间戳值,失败返回-1*/
long long get_current_timestamp_ms(void)
{
#if defined(_WIN32) || defined(_WIN64)struct _timeb timebuffer;_ftime64_s(&timebuffer);return (long long)timebuffer.time * 1000 + timebuffer.millitm;
#elif defined(__unix__) || defined(__unix) || defined(unix)struct timeval tv;gettimeofday(&tv, NULL);return (long long)tv.tv_sec * 1000 + tv.tv_usec / 1000;
#endif
}

参考代码运行结果

使用可视化工具SQLiteStudio,对SQLite3数据库进行查看。

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

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

相关文章

python:画饼图

我现在因工作需要在写一篇中文文章&#xff0c;领导要我用python处理数据和画图&#xff0c;那我也刚好学习一下python画图。 import matplotlib.pyplot as plt # 饼图数据 labels [A, B, C, D] sizes [15, 30, 45, 10] # 每个部分的大小 # 绘制饼图 plt.figure(figsize(6,…

紧跟生成式AI暴雨发布新时代推理服务器

近日&#xff0c;暴雨发布最新训推一体AI服务器&#xff0c;以大容量内存和灵活的高速互连选项满足各种AI应用场景&#xff0c;最大可能支持扩展插槽&#xff0c;从而大幅提升智能算力性能&#xff0c;以最优的性能和成本为企业的模型训练推理落地应用提供更好的通用算力。 AIG…

软考系列必过资料分享-系统架构师-系统分析师-信息系统项目管理师

建议,写在前面 知识点是公用的,原则上不分新旧。每年会有少部分的题目切合当前时间段&#xff08;也是通过旧的知识演变的&#xff09; 信息系统项目管理师证书 系统架构师证书 系统分析师证书 资料分享 关注公众号 回复 信息系统项目管理师资料 即可获取信息系统项目管理师资…

【RAG 论文】Dense X 检索:将“命题”作为检索粒度

论文&#xff1a;Dense X Retrieval: What Retrieval Granularity Should We Use? ⭐⭐⭐⭐ Code: github.com/ct123098/factoid-wiki 文章目录 一、论文速读二、命题&#xff08;Proposition&#xff09;三、FactoidWiki四、实验及分析4.1 Passage Retrieval 任务4.2 Open-Do…

VSCode-vue3.0-安装与配置-export default简单例子

文章目录 1.下载VSCode2.修改语言为中文3.辅助插件列表4.vue3模板文件简单例子5.总结 1.下载VSCode 从官网下载VSCode&#xff0c;并按下一步安装成功。 2.修改语言为中文 点击确认修改&#xff0c;如下图所示&#xff1a; 或者打开命令面板&#xff1a;输入Configure Displ…

党建教育vr虚拟现实展厅真正实现了绿色、低碳的展示方式

在数字化浪潮席卷的今天&#xff0c;传统企业门户官网已难以满足企业日益增长的展示需求。面对这一挑战&#xff0c;北京华锐凭借深厚的行业经验和领先的技术实力&#xff0c;为您提供全新的元宇宙虚拟展厅制作服务&#xff0c;助您轻松打破现实与虚拟的界限&#xff0c;开启企…

如何让vim支持python3

首先删除旧的vim。 sudo apt-get remove vim //输入re按下tab直接显示remove sudo apt-get remove vim-runtime sudo apt-get remove vim -tiny sudo apt-get remove vim-common 然后下载vim8源码&#xff1a; git clone https://github.com/vim/vim.git 进行编译安装…

【NodeMCU实时天气时钟温湿度项目 5】获取关于城市天气实况和天气预报的JSON信息(心知天气版)

| 今天是第五专题内容&#xff0c;主要是介绍如何从心知天气官网&#xff0c;获取包含当前天气实况和未来 3 天天气预报的JSON数据信息。 在学习获取及显示天气信息前&#xff0c;我们务必要对JSON数据格式有个深入的了解。 如您需要了解其它专题的内容&#xf…

C语言----杨辉三角

各位看官们好。学习到这里想必大家应该对C语言的了解也是很深刻的了吧。但是我们也不能忘记我们一起学习的知识啊。在我们以前学习C语言的时候我想大家应该都听说过杨辉三角吧。虽然我们把其中的规律找到那么这个代码就简单很多了。那么接下里我们就来讲讲杨辉三角。 首先我们先…

sql 注入 1

当前在email表 security库 查到user表 1、第一步&#xff0c;知道对方goods表有几列&#xff08;email 2 列 good 三列&#xff0c;查的时候列必须得一样才可以查&#xff0c;所以创建个临时表&#xff0c;select 123 &#xff09; 但是你无法知道对方goods表有多少列 用order …

场外期权个股怎么对冲?

今天期权懂带你了解场外期权个股怎么对冲&#xff1f;场外个股期权是一种在非交易所市场进行的期权交易&#xff0c;它允许投资者针对特定的股票获得未来买入或卖出的权利。 场外期权个股怎么对冲&#xff1f; 持有相反方向的期权&#xff1a;这是最直接的对冲方法&#xff0c…

Elasticsearch中的三种分页策略深度解析:原理、使用及对比

码到三十五 &#xff1a; 个人主页 在Elasticsearch中&#xff0c;分页是查询操作中不可或缺的一部分。随着数据量的增长&#xff0c;如何高效地分页查询数据急需需要面对的问题。Elasticsearch提供了三种主要的分页方式&#xff1a;from size、scroll和search_after。下面详细…

STM32系统架构

以下是STM32系统架构中的各个重要组件和功能&#xff1a; 组件描述Cortex-M内核ARM Cortex-M系列内核&#xff0c;如M0、M0、M3、M4、M7等Flash存储器存储程序代码和数据SRAM存储程序运行时数据和堆栈外设接口GPIO、SPI、I2C、UART、TIM、ADC、DAC、USB、CAN、Ethernet等时钟和…

大模型微调实战之强化学习 贝尔曼方程及价值函数(五)

大模型微调实战之强化学习 贝尔曼方程及价值函数&#xff08;五&#xff09; 现在&#xff0c; 看一下状态-动作值函数的示意图&#xff1a; 这个图表示假设首先采取一些行动(a)。因此&#xff0c;由于动作&#xff08;a&#xff09;&#xff0c;代理可能会被环境转换到这些状…

源代码烧录场景防泄密的四种方式

在各行各业中&#xff0c;外设烧录是一项常见的操作&#xff0c;涉及到对硬件设备进行固件更新或配置文件的写入。然而&#xff0c;外设烧录过程中的文件管理和安全审计一直是一个挑战&#xff0c;传统的烧录方法往往无法提供足够的安全保障。本文将介绍如何利用沙盒防泄密软件…

ENVI拓展工具资源去哪里找

ENVI拓展工具资源去哪里找&#xff1f; 文章目录 ENVI拓展工具资源去哪里找&#xff1f;前言网站&#xff08;链接见文末&#xff09;ENVI应用商店&#xff08;App Store&#xff09;ENVI官方提供第三方制作自己制作 总结参考 前言 ENVI 拓展工具是指 ENVI 软件的扩展功能或插…

Linux系统编程--网络编程

一、OSI网络七层模型 OSI模型将整个网络通信过程分解为七个层次&#xff0c;每个层次都为网络通信提供了特定的功能。以下是OSI模型的七个层次&#xff0c;从上到下依次是&#xff1a; 应用层&#xff08;Application Layer&#xff09;&#xff1a;为应用软件提供网络服务&am…

Python数据可视化------地图

基础地图使用 # 地图基本演示 # 导包 from pyecharts.charts import Map from pyecharts.options import TitleOpts, VisualMapOpts# 准备地图对象 cmap Map() # 准备数据&#xff08;列表&#xff09; data [("北京市", 99), ("上海市", 199), ("…

【大模型】LLaMA-1 模型介绍

文章目录 一、背景介绍二、模型介绍2.1 模型结构2.2 模型超参数2.3 SwiGLU 三、代码分析3.1 模型结构代码3.2 FairScale库介绍 四、LLaMA家族模型4.1 Alpaca4.2 Vicuna4.3 Koala(考拉)4.4 Baize (白泽)4.5 Luotuo (骆驼&#xff0c;Chinese)4.6 其他 参考资料 LLaMA&#xff08…

微信小程序16: 组件通信

父子组件之间的通信 父子组件通信一共有三种方式 属性绑定 用于父组件向子组件的指定属性设置数据&#xff0c;仅能设置JSON兼容的数据 事件绑定 用于子组件向父组件传递数据&#xff0c;可以传递任意数据 获取组件实例 父组件还可以通过this.selectComponent()获取子组件的实…