嵌入式数据库——API创建

SQLite C API 操作

一、核心 API 详解

1. sqlite3_open 打开数据库

函数原型

复制代码
int sqlite3_open(const char *filename, sqlite3 **db);

参数说明

参数名 含义
filename 数据库文件路径(字符串),支持:- 已存在的数据库文件路径- 新文件路径(文件不存在时自动创建)- 特殊值 ":memory:":创建内存数据库(进程结束数据丢失)
db 输出参数,指向 sqlite3* 类型的指针,函数执行成功后会将数据库句柄写入该指针

返回值

  • 成功:返回 SQLITE_OK(值为 0)
  • 失败:返回非 0 错误码(如文件权限不足、路径无效等)

示例代码

复制代码
sqlite3 *db;
int rc = sqlite3_open("student.db", &db);
if (rc != SQLITE_OK) {
    printf("打开数据库失败:%s\n", sqlite3_errmsg(db));
    exit(1);
}
printf("数据库打开成功\n");

2. sqlite3_close 关闭数据库

函数原型

复制代码
int sqlite3_close(sqlite3 *db);

参数说明

参数名 含义
db 数据库句柄,由 sqlite3_open 初始化

返回值

  • 成功:返回 SQLITE_OK(0)
  • 失败:返回非 0 错误码(如句柄未初始化、有未释放的资源)

注意事项

  • 关闭前需确保所有 sqlite3_execsqlite3_get_table 相关资源已释放(如 errmsgresultp
  • 关闭后句柄不可再使用,否则会导致程序崩溃

示例代码

复制代码
sqlite3_close(db);

3. sqlite3_errmsg 获取错误信息

函数原型

复制代码
const char *sqlite3_errmsg(sqlite3 *db);

参数说明

参数名 含义
db 数据库句柄

返回值

  • 错误信息字符串的首地址(只读,无需手动释放)

使用场景

  • sqlite3_open 失败时
  • sqlite3_execsqlite3_get_table 执行失败时
  • 其他 API 调用失败时

示例代码

复制代码
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK) {
    printf("SQL执行失败:%s\n", sqlite3_errmsg(db));
    sqlite3_free(errmsg); // 释放错误信息内存
}

4. sqlite3_exec 执行 SQL 语句(带回调)

函数原型

复制代码
int sqlite3_exec(
    sqlite3 *db,
    const char *sql,
    int (*callback)(void*, int, char**, char**),
    void *arg,
    char **errmsg
);

参数说明

参数名 含义
db 数据库句柄
sql 要执行的 SQL 语句(字符串),支持:- DDL 语句(CREATE TABLE/ALTER/DROP)- DML 语句(INSERT/UPDATE/DELETE)- DQL 语句(SELECT,需配合回调函数)
callback 回调函数指针,仅当 SQL 为SELECT查询语句时生效,每查询到一条记录自动调用一次
arg 传递给回调函数的自定义参数(无回调时传NULL
errmsg 输出参数,存储错误信息字符串的地址,需用sqlite3_free(errmsg)释放

返回值

  • 成功:SQLITE_OK(0)
  • 失败:非 0 错误码
回调函数详解

函数原型

复制代码
int callback(void *para, int f_num, char **f_value, char **f_name);

参数说明

参数名 含义
para sqlite3_exec 传递的自定义参数(即 arg
f_num 当前记录的字段数量(列数)
f_value 字段值数组,f_value[i] 为第i个字段的值(字符串形式)
f_name 字段名数组,f_name[i] 为第i个字段的名称

返回值

  • 成功:返回 0
  • 失败:返回非 0 值,会导致sqlite3_exec提前终止并返回错误码

示例:查询数据 + 回调函数

复制代码
// 回调函数:打印查询结果
int print_result(void *arg, int f_num, char **f_value, char **f_name) {
    int i;
    // 打印字段值
    for (i = 0; i < f_num; i++) {
        printf("%s = %s\t", f_name[i], f_value[i] ? f_value[i] : "NULL");
    }
    printf("\n");
    return 0;
}

// 执行查询SQL
void do_query(sqlite3 *db) {
    char *sql = "SELECT * FROM stu;";
    char *errmsg = NULL;
    if (sqlite3_exec(db, sql, print_result, NULL, &errmsg) != SQLITE_OK) {
        printf("查询失败:%s\n", errmsg);
        sqlite3_free(errmsg);
    }
}

5. sqlite3_get_table 执行 SQL(无回调)

函数原型

复制代码
int sqlite3_get_table(
    sqlite3 *db,
    const char *sql,
    char ***resultp,
    int *nrow,
    int *ncolumn,
    char **errmsg
);

参数说明

参数名 含义
db 数据库句柄
sql 要执行的 SQL 语句(主要用于SELECT查询)
resultp 输出参数,指向查询结果的二维数组指针,格式为:- 第 0 行:字段名- 第 1~n 行:字段值
nrow 输出参数,查询结果的记录行数(不含字段名行)
ncolumn 输出参数,查询结果的字段列数
errmsg 输出参数,错误信息字符串地址,需用sqlite3_free(errmsg)释放

返回值

  • 成功:SQLITE_OK(0)
  • 失败:非 0 错误码

注意事项

  • 查询完成后,需调用 sqlite3_free_table(resultp) 释放结果内存
  • resultp 数组中,resultp[0~nrow*ncolumn-1] 为所有字段名 + 字段值

示例:无回调查询数据

复制代码
void do_query_no_callback(sqlite3 *db) {
    char *sql = "SELECT * FROM stu;";
    char **resultp = NULL;
    int nrow, ncolumn;
    char *errmsg = NULL;
    int i, j, index;

    if (sqlite3_get_table(db, sql, &resultp, &nrow, &ncolumn, &errmsg) != SQLITE_OK) {
        printf("查询失败:%s\n", errmsg);
        sqlite3_free(errmsg);
        return;
    }

    // 打印字段名(第0行)
    printf("===== 查询结果(共%d条记录)=====\n", nrow);
    for (i = 0; i < ncolumn; i++) {
        printf("%s\t", resultp[i]);
    }
    printf("\n");

    // 打印字段值(第1~nrow行)
    index = ncolumn; // 跳过字段名行
    for (i = 0; i < nrow; i++) {
        for (j = 0; j < ncolumn; j++) {
            printf("%s\t", resultp[index++]);
        }
        printf("\n");
    }

    // 释放结果内存
    sqlite3_free_table(resultp);
}

二、代码实现

复制代码
#include<stdio.h>
#include<stdlib.h>
#include<sqlite3.h>

#define DATABASE "student.db"

int do_insert(sqlite3* db)
{
	int id;
	char name[32] = {};
	int score;
	
	char sql[128] = {};
	char* errmsg = NULL;

	printf("please input id:");
	scanf("%d",&id);
	
	printf("please input name:");
	scanf("%s",name);

	printf("please input score:");
	scanf("%d",&score);

	sprintf(sql,"insert into stu values(%d,'%s',%d);",id,name,score);
	if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
	{
		printf("%s\n",errmsg);
        sqlite3_free(errmsg);
		exit(0);
	}
	else
	{
		printf("insert succeed\n");
	}
	return 0;
}

int do_delete(sqlite3 *db)
{
	int id;
	char sql[128] = {0};

	char *errmsg = NULL;

	printf("please input id:");
	scanf("%d",&id);

	sprintf(sql,"delete from stu where id=%d;",id);

	if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
	{
		printf("%s\n",errmsg);
        sqlite3_free(errmsg);
		exit(0);
	}
	else
	{
		printf("delete succeed\n");
	}
	return 0;
}

int do_update(sqlite3 *db)
{
        int id;
        char sql[128] = {0};
	int score;

        char *errmsg = NULL;

        printf("please input id:");
        scanf("%d",&id);

	printf("please input score:");
	scanf("%d",&score);

        sprintf(sql,"update stu set score = %d where id = %d;",score,id);

        if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
        {
                printf("%s\n",errmsg);
                sqlite3_free(errmsg);
                exit(0);
        }
        else
        {
                printf("update succeed\n");
        }
        return 0;
}

int callback(void *para,int f_num,char **f_value,char **f_name)
{
	int  i = 0;
	for(i=0;i<f_num;i++)
	{
		printf("%-11s",f_value[i]);
	}
	putchar(10);
	return 0;
}

int do_query1(sqlite3 *db)
{
	char sql[128] = {};
	char *errmsg = NULL;

	sprintf(sql,"select * from stu;");

	if(sqlite3_exec(db,sql,callback,NULL,&errmsg) != SQLITE_OK)
	{
		printf("%s\n",errmsg);
        sqlite3_free(resultp);
		exit(0);
	}
	else
	{
		printf("query succeed\n");
	}
	return 0;
}

int do_query2(sqlite3 *db)
{
	char sql[128] = {};
	char *errmsg = NULL;

	char **resultp;
	int nrow;
	int ncloumn;
	int i,j,index;

	sprintf(sql,"select * from stu;");

	if(sqlite3_get_table(db,sql,&resultp,&nrow,&ncloumn,&errmsg) != SQLITE_OK)
	{
		printf("%s\n",errmsg);
        sqlite3_free(errmsg);
		exit(0);
	}
	else
	{
		printf("query succeed\n");
	}

	
	for(j=0;j<ncloumn;j++)
	{
		printf("%-11s",resultp[j]);
	}
	putchar(10);

    index = ncloumn;

	for(i=0;i<nrow;i++)
	{
		for(j=0;j<ncloumn;j++)
		{
			printf("%-11s",resultp[index++]);
		}
		putchar(10);
	}
    sqlite3_free_table(resultp);
	return 0;
}

int main()
{
	sqlite3* db;
	char* errmsg = NULL;
	int cmd;

	if(sqlite3_open(DATABASE,&db) != SQLITE_OK)
	{
		printf("%s\n",sqlite3_errmsg(db));
		exit(1);
	}
	else
	{
		printf("open sqlite succeed\n");
	}

	if(sqlite3_exec(db,"create table if not exists stu(id Integer,name char,score Integer);",NULL,NULL,&errmsg) != SQLITE_OK)
	{
		printf("%s\n",sqlite3_errmsg(db));
	}
	else
	{
		printf("create or open table secceed\n");
	}
	while(1)
	{
		printf("************************\n");
		printf("1:inster,2:delete,3:query,4:update,5:quit\n");
		printf("**********************\n");
		printf("please input cmd:\n");

		scanf("%d",&cmd);
		getchar();
		switch(cmd)
		{
			case 1:
				do_insert(db);
				break;
			case 2:
				do_delete(db);
				break;
			case 3:
				do_query2(db);
				break;
			case 4:
				do_update(db);
				break;
			case 5:
				sqlite3_close(db);
				exit(0);
			default:
				printf("cmd err\n");
		}
	}

	return 0;
}

1、先讲:main 函数(程序入口,最重要)

复制代码
int main()
{
    // 1. 定义数据库句柄指针、错误信息指针、命令选项
    sqlite3* db;
    char* errmsg = NULL;
    int cmd;
  • sqlite3 *db:数据库句柄,相当于数据库的 "钥匙",所有操作都靠它。

  • errmsg:存放错误信息,操作失败时会把原因存在这里。

  • cmd:接收用户输入的菜单选项(1 插入 2 删除 3 查询 4 修改 5 退出)。

    复制代码
      // 2. 打开数据库(不存在则自动创建)
      if(sqlite3_open(DATABASE,&db) != SQLITE_OK)
      {
          printf("%s\n",sqlite3_errmsg(db));
          exit(1);
      }
      else
      {
          printf("open sqlite succeed\n");
      }
  • sqlite3_open("student.db", &db)

    • 打开 student.db 文件
    • 不存在则自动创建
    • 成功返回 SQLITE_OK(0)
  • 失败:打印错误信息并退出。

  • 成功:打印 "打开数据库成功"

    复制代码
      // 3. 创建数据表 stu
      if(sqlite3_exec(db,"create table if not exists stu(id Integer,name char,score Integer);",NULL,NULL,&errmsg) != SQLITE_OK)
      {
          printf("%s\n",sqlite3_errmsg(db));
      }
      else
      {
          printf("create or open table secceed\n");
      }
  • 执行 SQL:create table stu(...)

  • 创建一张表,包含三列:

    • id:整数
    • name:字符串
    • score:分数
  • 如果表已经存在,会报错,但不影响程序运行

    复制代码
      // 4. 死循环:菜单界面
      while(1)
      {
          printf("************************\n");
          printf("1:inster,2:delete,3:query,4:update,5:quit\n");
          printf("**********************\n");
          printf("please input cmd:\n");
    
          // 读取用户输入的命令
          scanf("%d",&cmd);
    
          // 根据命令执行对应功能
          switch(cmd)
          {
              case 1: do_insert(db);  break;  // 插入
              case 2: do_delete(db);  break;  // 删除
              case 3: do_query2(db);  break;  // 查询
              case 4: do_update(db);  break;  // 修改
              case 5: sqlite3_close(db); exit(0);  // 退出
              default: printf("cmd err\n");
          }
      }
      return 0;

    }

  • while(1):无限循环显示菜单

  • scanf 读取用户输入 1~5

  • switch 分支:

    • 1 → 插入
    • 2 → 删除
    • 3 → 查询
    • 4 → 修改
    • 5 → 关闭数据库并退出
  • getchar():吸收回车,避免输入冲突

2、功能函数 1:do_insert(插入数据)

复制代码
int do_insert(sqlite3* db)
{
    int id;
    char name[32] = {};
    int score;
    char sql[128] = {};
    char* errmsg = NULL;

    // 输入 id、姓名、分数
    printf("please intput id:");
    scanf("%d",&id);

    printf("please intput name:");
    scanf("%s",name);

    printf("please intput score:");
    scanf("%d",&score);
  • 定义变量接收用户输入:

    • 学号 id

    • 姓名 name

    • 成绩 score

      复制代码
      // 拼接 SQL 插入语句
      sprintf(sql,"insert into stu values(%d,'%s',%d);",id,name,score);
  • 把输入的内容拼成一句 SQL: sql

    复制代码
    insert into stu values(1001,'张三',88);
    
      // 执行 SQL
      if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
      {
          printf("%s\n",errmsg);
          sqlite3_free(errmsg);
          exit(0);
      }
      else
      {
          printf("insert succeed\n");
      }
      return 0;

    }

  • sqlite3_exec:执行 SQL 语句

  • 成功:打印插入成功

  • 失败:打印错误并退出

3、功能函数 2:do_delete(按 id 删除数据)

复制代码
int do_delete(sqlite3 *db)
{
    int id;
    char sql[128] = {0};
    char *errmsg = NULL;

    printf("please input id:");
    scanf("%d",&id);

    // 拼接删除 SQL
    sprintf(sql,"delete from stu where id=%d;",id);

    // 执行删除
    if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
    {
        printf("%s\n",errmsg);
        sqlite_3 free(errmsg);
        exit(0);
    }
    else
    {
        printf("delete succeed\n");
    }
    return 0;
}
  • 功能:根据 id 删除一条学生记录

  • SQL 语句: sql

    复制代码
    delete from stu where id=1001;
  • 执行成功输出 delete succeed

4、功能函数 3:do_update(修改成绩)

复制代码
int do_update(sqlite3 *db)
{
    int id, score;
    char sql[128] = {0};
    char *errmsg = NULL;

    printf("please input id:");
    scanf("%d",&id);

    printf("please input score:");
    scanf("%d",&score);

    // 拼接修改 SQL
    sprintf(sql,"update stu set score = %d where id = %d;",score,id);

    // 执行修改
    if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
    {
        printf("%s\n",errmsg);
        sqlite3_free(errmsg);
        exit(0);
    }
    else
    {
        printf("update succeed\n");
    }
    return 0;
}
  • 功能:根据 id 修改学生成绩

  • SQL 语句: sql

    复制代码
    update stu set score=99 where id=1001;
  • 执行成功输出 update succeed

5、功能函数 4:callback(查询回调函数)

复制代码
int callback(void *para,int f_num,char **f_value,char **f_name)
{
    int  i = 0;
    for(i=0;i<f_num;i++)
    {
        printf("%s",f_value[i]);
    }
    putchar(10);
    return 0;
}
  • do_query1 查询使用
  • 每查到一条数据,自动调用一次
  • f_value 是字段值
  • 作用:打印查询到的一条数据

6、功能函数 5:do_query1(回调查询)

复制代码
int do_query1(sqlite3 *db)
{
    char sql[128] = {};
    char *errmsg = NULL;

    sprintf(sql,"select * from stu;");

    if(sqlite3_exec(db,sql,callback,NULL,&errmsg) != SQLITE_OK)
    {
        printf("%s\n",errmsg);
        sqlite3_free(errmsg);
        exit(0);
    }
    else
    {
        printf("query succeed\n");
    }
    return 0;
}
  • 使用 sqlite3_exec + 回调 方式查询
  • 查询所有学生数据
  • 查到数据 → 自动进入 callback 打印

7、功能函数 6:do_query2(无回调查询,最常用)

复制代码
int do_query2(sqlite3 *db)
{
    char sql[128] = {};
    char *errmsg = NULL;
    char **resultp;
    int nrow;     // 行数
    int ncloumn;  // 列数
    int i,j,index;

    sprintf(sql,"select * from stu;");
  • sqlite3_get_table不需要回调,直接把所有结果存到二维数组

  • resultp:存储所有查询结果

  • nrow:多少行数据

  • ncolumn:多少列

    复制代码
      if(sqlite3_get_table(db,sql,&resultp,&nrow,&ncloumn,&errmsg) != SQLITE_OK)
      {
          printf("%s\n",errmsg);
          sqlite3_free(errmsg);
          exit(0);
      }
      else
      {
          printf("query succeed\n");
      }
  • 执行查询,结果存入 resultp

    复制代码
      // 打印表头
      for(j=0;j<ncloumn;j++)
      {
          printf("%-11s",resultp[j]);
      }
      putchar(10);
    
      // 打印每一行数据
      index = ncloumn;
      for(i=0;i<nrow;i++)
      {
          for(j=0;j<ncloumn;j++)
          {
              printf("%-11s",resultp[index++]);
          }
          putchar(10);
      }
      return 0;

    }

  • 先打印字段名(id name score)

  • 再循环打印每一行数据

  • 格式对齐,非常整齐

总结

  1. main 函数:打开数据库 → 创建表 → 显示菜单 → 调用功能函数
  2. do_insert:输入信息 → 拼接 SQL → 插入数据库
  3. do_delete:输入 id → 删除对应数据
  4. do_update:输入 id 和新成绩 → 修改数据
  5. callback:查询时自动打印数据
  6. do_query1:回调方式查询
  7. do_query2:无回调、直接表格打印(最常用)

所有功能全部实现,成功执行。

相关推荐
m0_746752302 小时前
c++怎么利用std--variant处理多种二进制子协议包的自动分支解析【进阶】
jvm·数据库·python
Lucifer三思而后行2 小时前
中标麒麟 NeoKylin V7 一键安装 Oracle 12CR2 ASM(240116)
数据库·oracle
m0_734949798 小时前
MySQL如何配置定时清理过期备份文件_find命令与保留周期策略
jvm·数据库·python
m0_514520579 小时前
MySQL索引优化后性能没提升_通过EXPLAIN查看索引命中率
jvm·数据库·python
NaMM CHIN9 小时前
sql实战解析-sum()over(partition by xx order by xx)
数据库·sql
不瘦80斤不改名9 小时前
深入浅出 MySQL(一):一文理清 SQL 核心规范与五大分类
数据库·sql·mysql
woniu_buhui_fei9 小时前
MySQL知识整理二
数据库·mysql
Polar__Star10 小时前
如何在 AWS Lambda 中正确使用临时凭证生成 S3 预签名 URL
jvm·数据库·python
Lucifer三思而后行10 小时前
zCloud 中 Oracle 实例状态未知问题记录
数据库·oracle