在嵌入式开发和C语言数据结构的学习旅程中,数据持久化是一个绕不开的核心话题。当我们从简单的内存操作过渡到复杂的系统开发时,如何使用普通文件高效地管理数据?又该如何在嵌入式设备中引入轻量级的数据库?
今天这篇博客,将结合底层数据结构与C语言API,带你从零开始系统梳理数据库的基础概念、SQLite3的核心操作,以及如何用C语言操控它。文章包含多种图表和结构,建议收藏反复阅读。
一、 为什么需要数据库?(思维导图结构)
在嵌入式初期,我们往往直接使用普通文件(如txt、二进制文件)存储数据。但随着数据量增大,你会发现:
-
普通文件
-
对数据管理(增删改查)效率低
-
-
数据库
-
对数据管理效率高,使用方便
-
常用数据库分类
为了应对不同的业务场景,我们需要了解主流数据库的选型。可以通过以下思维导图来梳理:
-
关系型数据库 (将复杂的数据结构简化为二维表格形式)
-
大型:Oracle、DB2
-
中型:MySQL、SQL Server
-
小型:SQLite
-
-
非关系型数据库 (以键值对存储,且结构不固定,例如JSON)
-
Redis
-
MongoDB
-
为什么选择 SQLite3?(嵌入式首选)
在Linux嵌入式中,sqlite3(生成文件如 stu.db)是我们的老朋友。它具有以下无与伦比的优势:
-
开源免费,纯C语言开发
-
代码量少,1万行左右,总大小10M以内
-
文件型数据库,可以移动
-
数据容量最大2T
二、 SQLite3 环境搭建与基础命令
在Linux环境下(如Ubuntu),安装非常简单。我们可以通过apt包管理器完成:
bash
# 在线安装 sudo apt-get install sqlite3 sudo apt-get install libsqlite3-dev
安装完成后,通过命令行创建和进入数据库:
bash
# 创建数据库 sqlite3 xxx.db
进入数据库终端后,掌握以下几个元命令(Meta-commands)能让你的调试事半功倍。整理成表格如下:
| 元命令 | 作用说明 |
|---|---|
.help | 查看帮助信息 |
.tables | 查看数据库中的表名 |
.headers on/off | 打开/关闭表头 |
.mode column | 设置表左对齐 |
.quit | 退出数据库 |
💡 进阶工具:可视化查看
如果不习惯在黑框里操作,可以安装可视化工具:
-
Ubuntu端:
sudo apt-get install sqlitebrowser,打开使用sqlitebrowser xxx.db。 -
Windows端:推荐使用
NavicatSQLite3。
三、 SQLite3 SQL语句核心语法
SQLite3的SQL语句不区分大小写。它支持的数据类型包括:NULL、INTEGER(整型)、REAL(浮点型)、TEXT(字符串文本)、BLOB(根据输入确定)。
以下整理了常用的增删改查(CRUD)SQL语句,方便查阅:
1. 表操作
sql
-- 创建表 create table 表名(列名1 数据类型1, 列名2 数据类型2, 列名3 数据类型3); CREATE TABLE class1(id INTEGER, name TEXT, score REAL); -- 删除表 drop table 表名; -- 创建带有主键自动增长的表 create table 表名(列名 INTEGER PRIMARY KEY AUTOINCREMENT, 列名 数据类型);
2. 插入数据
sql
insert into 表名 values(值1, 值2, 值3); -- 注意:TEXT类型的数据,插入时需要用 "", '' 引起 insert into class1 values(1, "zhangsan", 88.5);
3. 查询数据(重点掌握)
sql
-- 查找所有数据 select * from 表名; -- 查找指定列数据 select 列名1, 列名2 from 表名; -- 条件查找 select * from where id=1; -- 关系运算符支持:= > >= <= < != -- 连接多个条件 select * from 表名 where 条件1 and 条件2; select * from 表名 where 条件1 or 条件2; -- 模糊查找 -- % : 模糊匹配若干个字符 -- _ : 模糊匹配一个字符 select * from class1 where name like "马%"; select * from class1 where name like "马__"; -- 如匹配“马冬梅” -- 有序查找 select * from 表名 order by 列名 ASC; -- 升序 select * from 表名 order by 列名 DESC; -- 降序
4. 修改与删除数据
sql
-- 修改 update 表名 set 列=新值 where 条件; -- 删除 delete from 表名 where 条件;
四、 SQLite3 提供的 C/C++ API接口实战
对于嵌入式和C语言开发者来说,将数据库融入C代码才是最终目的。SQLite3提供了一套简洁的C API。以下逐一解析。
4.1 sqlite3_open:打开数据库
c
int sqlite3_open(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
-
功能:打开一个数据库文件。
-
参数:
filename是数据库名称;ppdb是保存数据库句柄的指针(sqlite3 *)。 -
返回值:成功返回
SQLITE_OK,失败返回错误码。
4.2 sqlite3_errmsg:获取错误信息
c
const char *sqlite3_errmsg(sqlite3* pdb);
-
功能:获取当前数据库错误码对应的错误信息。
-
参数:
pdb为数据库句柄。 -
返回值:返回错误信息字符串。
4.3 sqlite3_exec:执行SQL语句的中枢
c
int sqlite3_exec(
sqlite3* pdb, /* An open database */
const char *sql, /* SQL to be evaluated */
int (*callback)(void*,int,char**,char**), /* Callback function */
void *arg, /* 1st argument to callback */
char **errmsg /* Error msg written here */
);
-
功能:执行SQL语句。
-
参数:
pdb句柄;sql要执行的SQL语句;callback回调函数,当select查询时,若查询到数据,会触发回调函数执行;arg传递给callback的参数(实参);errmsg保存出错信息。 -
返回值:成功返回
SQLITE_OK,失败返回错误码。
4.4 深入理解 Callback 回调函数
回调机制是 sqlite3_exec 最精妙的地方:
c
int (*callback)(void *arg, int n, char **value, char **name);
-
功能:select查询到数据时执行的回调函数。
-
参数:
-
arg:由sqlite3_exec的第4个参数传递的参数值(形参)。 -
n:select查询到的数据的列数。 -
value:查找到的数据的每一列的值char *value[]。 -
name:查找到的数据列的表头char *name[]。
-
-
返回值:成功返回0,失败返回1(非0)。
⚠️ 新手避坑指南(必看):
-
callback必须要有返回值,返回0表示正常; -
当select查询数据时,每找到一条数据,callback就会被触发一次;
-
数据库中的数据,通过select查询出时,统一按照字符串处理(即使定义为INTEGER或REAL,在回调的value里也是字符串,C语言中需要按需转换,如
atoi())。
学习小结
从普通文件到关系型数据库,再到非关系型数据库;从SQLite3的命令行操作,到C语言API的 sqlite3_open、sqlite3_exec 与回调函数。对于嵌入式新手来说,这条学习路径非常平滑。掌握这些内容,你已经能够为你的嵌入式项目(比如智能家居网关、数据采集器)添加可靠的本地数据存储能力了!建议结合图片中的代码片段,在Linux环境下亲手敲一遍,体验C语言与数据库碰撞的魅力。

308

被折叠的 条评论
为什么被折叠?



