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_exec、sqlite3_get_table相关资源已释放(如errmsg、resultp) - 关闭后句柄不可再使用,否则会导致程序崩溃
示例代码
sqlite3_close(db);
3. sqlite3_errmsg 获取错误信息
函数原型
const char *sqlite3_errmsg(sqlite3 *db);
参数说明
| 参数名 | 含义 |
|---|---|
db |
数据库句柄 |
返回值
- 错误信息字符串的首地址(只读,无需手动释放)
使用场景
sqlite3_open失败时sqlite3_exec、sqlite3_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)
-
再循环打印每一行数据
-
格式对齐,非常整齐
总结
- main 函数:打开数据库 → 创建表 → 显示菜单 → 调用功能函数
- do_insert:输入信息 → 拼接 SQL → 插入数据库
- do_delete:输入 id → 删除对应数据
- do_update:输入 id 和新成绩 → 修改数据
- callback:查询时自动打印数据
- do_query1:回调方式查询
- do_query2:无回调、直接表格打印(最常用)





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