外观
SQLite 学生信息管理示例
2025-09-22
概述
本示例演示如何在 RC3506 开发板上使用 SQLite 数据库,通过 RT-Thread 的 MSH 命令实现学生信息的增删改查, 帮助用户掌握在嵌入式环境中使用轻量级关系型数据库进行数据持久化的方法。
SQLite 简介
SQLite 是一款轻量级的嵌入式关系型数据库,无需独立的服务进程,整个数据库存储在单个文件中。 它支持标准 SQL 语法,核心库体积仅几百 KB,非常适合资源受限的嵌入式场景。 本示例通过 RT-Thread 的 sqlite_dbhelper 接口封装了常用的数据库操作。
创建工程点击展开
依次点击 “文件” -> “新建” -> "RT-Thread RuiChing App 项目"。

在弹出新建向导中选择 开发版 、BSP: 、示例 、 调试器/下载器。选择好之后点击 “完成”。

点击 “完成” 后,等待工程创建完成。

创建完成。

构建工程点击展开
单击工程使工程进入 Active-Debug 模式。

点击工具栏上的构建按钮进行工程编译。

构建成功后,会显示构建成功的信息。

固件下载点击展开
固化设备树

固化 APP

核心示例代码
学生管理模块相关代码
student 结构体:定义学生数据模型,包含 id、姓名、成绩三个字段,使用rt_list_t实现链表节点,支持将查询结果串联成链表;stu 命令:解析参数分发到 add、del、update、score 等子命令,实现完整的增删改查功能;create_student_tbl:检查数据库文件是否存在,不存在则自动建库建表。
- 定义学生数据模型
学生结构体包含 id、姓名、成绩三个字段,通过 rt_list_t 实现链表节点,支持将查询结果串联成链表。
sqlite_student_dao.c
struct student
{
unsigned int id;
char name[32];
int score;
rt_list_t list;
};
typedef struct student student_t;- 注册 MSH 命令并分发子命令
stu命令解析argc/argv参数,根据子命令分发到对应的增删改查操作。无参数时查询全部学生记录。
sqlite_student_dao.c
static void stu(uint8_t argc, char **argv)
{
if (argc < 2)
{
list_all();
return;
}
else
{
char *cmd = argv[1];
int rand = 0;
if (rt_strcmp(cmd, "add") == 0)
{
int i = 0, count = 0;
if (argc >= 3)
{
count = atol(argv[2]);
}
if (count == 0)
{
count = 1;
}
rt_tick_t ticks = rt_tick_get();
rand = ticks;
rt_list_t *h = (rt_list_t *)rt_calloc(1, sizeof(rt_list_t));
rt_list_init(h);
for (i = 0; i < count; i++)
{
student_t *s = (student_t *)rt_calloc(1, sizeof(student_t));
rand += i;
rand %= 99999;
s->score = (rand % 81) + 20;
sprintf(s->name, "Student%d", rand);
rt_list_insert_before(h, &(s->list));
}
int res = student_add(h);
student_free_list(h);
if (res != SQLITE_OK)
{
LOG_E("add failed!");
}
else
{
ticks = rt_tick_get() - ticks;
rt_kprintf("Insert %d record(s): %dms, speed: %dms/record\n", count,
ticks * 1000 / RT_TICK_PER_SECOND, ticks * 1000 / RT_TICK_PER_SECOND / count);
}
}
else if (rt_strcmp(cmd, "del") == 0)
{
if (argc == 2)
{
if (student_del_all() == SQLITE_OK)
{
rt_kprintf("Del all record success!\n");
}
else
{
rt_kprintf("Del all record failed!\n");
}
}
else
{
rt_uint32_t id = atol(argv[2]);
if (student_del(id) == SQLITE_OK)
{
rt_kprintf("Del record success with id:%d\n", id);
}
else
{
rt_kprintf("Del record failed with id:%d\n", id);
}
}
}
else if (rt_strcmp(cmd, "update") == 0)
{
/* update student record by id */
if (argc >= 5)
{
student_t *s = rt_calloc(sizeof(student_t), 1);
s->id = atol(argv[2]);
rt_strncpy(s->name, argv[3], rt_strlen(argv[3]));
s->score = atol(argv[4]);
if (student_update(s) == SQLITE_OK)
{
rt_kprintf("update record success!\n");
}
else
{
rt_kprintf("update record failed!\n");
}
rt_free(s);
}
else
{
rt_kprintf("usage: stu update id name score\n");
}
}
else if (rt_strcmp(cmd, "score") == 0)
{
/* query student's score between LOW and HIGH. */
if (argc >= 4)
{
enum order_type order = ASC;
int ls = atol(argv[2]);
int hs = atol(argv[3]);
if (rt_strcmp(argv[4], "-d") == 0)
{
order = DESC;
}
list_by_score(ls, hs, order);
}
else
{
rt_kprintf("usage: stu score LOW HIGH [OPTION]\n"
"desc:query student's score between LOW and HIGH.\n"
"OPTION(default ascending):\n -a:ascending\n -d:descending\n"
"e.g: stu score 60 100 or stu score -d 60 100\n");
}
}
else
{
student_t *s = rt_calloc(sizeof(student_t), 1);
rt_uint32_t id = atol(argv[1]);
if (student_get_by_id(s, id) > 0)
{
rt_kprintf("id:%d\t\tname:%s\tscore:%d\n", s->id, s->name, s->score);
}
else
{
rt_kprintf("no record with id:%d\n", id);
}
rt_free(s);
}
}
}
MSH_CMD_EXPORT(stu, student add del update query);- 建库建表
create_student_tbl 检查数据库文件是否存在,不存在则创建数据库和表;文件存在则检查表是否存在。
sqlite_student_dao.c
static int create_student_tbl(void)
{
int fd = -1;
static const char *CREATE_STUDENT_SQL =
"CREATE TABLE student(id INTEGER PRIMARY KEY AUTOINCREMENT,name varchar(32) NOT NULL,score INT NOT NULL);";
db_set_name("/data/stu_info.db");
const char *db_name = db_get_name();
rt_kprintf("Database path: %s\n", db_name);
fd = open(db_name, O_RDONLY);
if (fd < 0)
{
int ret = db_create_database(CREATE_STUDENT_SQL);
if (ret != RT_EOK)
{
LOG_E("Failed to create database/table!\n");
}
return ret;
}
else
{
int table_exist = db_table_is_exist("student");
close(fd);
if (table_exist > 0)
{
LOG_I("Table 'student' already exists!\n");
return RT_EOK;
}
else
{
int ret = db_create_database(CREATE_STUDENT_SQL);
if (ret != RT_EOK)
{
LOG_E("Failed to create table 'student'!\n");
}
return ret;
}
}
}运行示例
操作步骤:
- 将程序下载到开发板
- 打开串口终端连接开发板
- 输入 create_student_tbl 命令创建数据库和表
- 使用 stu 命令进行增删改查操作
操作指令:
| 命令 | 说明 |
|---|---|
create_student_tbl | 创建数据库文件和 student 表 |
stu | 查询全部学生记录 |
stu add [n] | 批量插入 n 条随机学生记录,默认 1 条 |
stu <id> | 按 id 查询单条学生记录 |
stu update <id> <name> <score> | 按 id 更新学生姓名和成绩 |
stu del <id> | 删除指定 id 的学生记录 |
stu del | 删除全部学生记录 |
stu score <low> <high> [-d] | 按成绩范围查询 |
预期结果:
- 运行
create_student_tbl:创建数据库文件/data/stu_info.db和 student 表 - 运行
stu add 10:批量插入 10 条随机学生记录,并显示插入耗时 - 运行
stu:查询并打印全部学生信息 - 运行
stu update <id> <name> <score>:修改指定学生信息 - 运行
stu del <id>:删除指定学生记录 - 运行
stu score <低分> <高分> [-d]:按成绩范围查询,-d 为降序
msh />create_student_tbl
Database path: /data/stu_info.db
msh />stu add 10
Insert 10 record(s): 31ms, speed: 3ms/record
msh />stu
test get all students
id:1 name:Student38712 score:95
id:2 name:Student38713 score:96
id:3 name:Student38715 score:98
id:4 name:Student38718 score:20
id:5 name:Student38722 score:24
id:6 name:Student38727 score:29
id:7 name:Student38733 score:35
id:8 name:Student38740 score:42
id:9 name:Student38748 score:50
id:10 name:Student38757 score:59
record(s):10
msh />stu 1
id:1 name:Student38712 score:95
msh />stu update 1 Tom 95
update record success!
msh />stu score 60 100
the student list of score between 60 and 100:
id:1 name:Tom score:95
id:2 name:Student38713 score:96
id:3 name:Student38715 score:98
record(s):3
msh />stu del 1
Del record success with id:1
msh />stu del
Del all record success!