详情

首页手游攻略 嵌入式数据库SQLite 3配置使用讲解实用指南

嵌入式数据库SQLite 3配置使用讲解实用指南

佚名 2026-09-01 19:20:01

平时做技术实践时,很多问题不是概念不会,而是细节没串起来。拿“嵌入式数据库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 Filessqlite路径下。

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

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

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

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

(5)、SQLiteStudio工具

如果有可视化分析数据需求、建议采用下载:SQLiteStudio

(链接已移除)

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: %sn", sqlite3_errmsg(db));
    exit(-1);
}
fprintf(stderr, "Opened database successfullyn");

(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:%sn", err_msg);
    return -1;
}
fprintf(stderr, "create table successfullyn");

(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:%sn", err_msg);
    return -1;
}
fprintf(stderr, "delete table successfullyn");

(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:%sn", err_msg);
    return -1;
}
fprintf(stderr, "insert value to table successfullyn");

(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: %sn", 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: %sn", 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: %sn", 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:%sn", database_name);
   //打开数据库
    ret = sqlite3_open(database_name, &db);
    if( ret )
    {
        fprintf(stderr, "Can't open database: %sn", sqlite3_errmsg(db));
        return -1;
    }
    fprintf(stderr, "Opened database successfullyn");
    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:%sn", err_msg);
            return -1;
        }
        fprintf(stderr, "create table successfullyn");
    }
    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:%sn", err_msg);
        return -1;
    }
    fprintf(stderr, "create table successfullyn");
    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:%sn", err_msg);
        return -1;
    }
    fprintf(stderr, "insert value to table successfullyn");
    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:%sn", err_msg);
        return -1;
    }
    fprintf(stderr, "insert value to table successfullyn");
    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数据库进行查看。

到此这篇关于嵌入式数据库SQLite 3设置采用详细笔记教程的文章就介绍到这了,更多相关嵌入式数据库SQLite 3内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多兼容脚本之家!

您可能感兴趣的文章:
  • Android编程操作嵌入式关系型SQLite数据库实例详解
  • SQLite3 在嵌入式C环境中存储音频/视频文件的最优方案
  • SQLite3 在嵌入式系统中的集成步骤
点击查看更多
推荐专题
热门阅读