【AI大模型接入SDK】SQLite基础概念与C的API开发

🎬 个人主页艾莉丝努力练剑
专栏传送门 :《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录
Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享

⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平


🎬 艾莉丝的简介:


文章目录

  • [1 ~> SQLite 基础概念](#1 ~> SQLite 基础概念)
    • [1.1 SQLite 存储类](#1.1 SQLite 存储类)
    • [1.2 亲和类型 (Affinity)](#1.2 亲和类型 (Affinity))
      • [1.2.1 五种亲和类型](#1.2.1 五种亲和类型)
      • [1.2.2 建表类型名与亲和类型映射](#1.2.2 建表类型名与亲和类型映射)
    • [1.3 SQLite 常用 SQL 语法分类](#1.3 SQLite 常用 SQL 语法分类)
  • [2 ~> SQLite C/C++ 开发环境](#2 ~> SQLite C/C++ 开发环境)
    • [2.1 开发依赖](#2.1 开发依赖)
    • [2.2 编译链接命令](#2.2 编译链接命令)
      • [2.2.1 GCC/G++ 命令](#2.2.1 GCC/G++ 命令)
      • [2.2.2 Makefile](#2.2.2 Makefile)
      • [2.2.3 CMakeLists.txt](#2.2.3 CMakeLists.txt)
  • [3 ~> SQLite C API 核心模块](#3 ~> SQLite C API 核心模块)
    • [3.1 数据库连接管理 API](#3.1 数据库连接管理 API)
      • [3.1.1 sqlite3_open](#3.1.1 sqlite3_open)
      • [3.1.2 sqlite3_close](#3.1.2 sqlite3_close)
      • [3.1.3 sqlite3_errmsg](#3.1.3 sqlite3_errmsg)
    • [3.2 SQL 预处理编译 API(prepare‑v2)](#3.2 SQL 预处理编译 API(prepare‑v2))
      • [3.2.1 sqlite3_prepare_v2](#3.2.1 sqlite3_prepare_v2)
      • [3.2.2 SQL 占位符(参数绑定)](#3.2.2 SQL 占位符(参数绑定))
    • [3.3 参数绑定 API(bind 系列)](#3.3 参数绑定 API(bind 系列))
      • [3.3.1 sqlite3_bind_int64](#3.3.1 sqlite3_bind_int64)
      • [3.3.2 sqlite3_bind_text](#3.3.2 sqlite3_bind_text)
    • [3.4 SQL 执行 API](#3.4 SQL 执行 API)
      • [3.4.1 sqlite3_exec](#3.4.1 sqlite3_exec)
      • [3.4.2 sqlite3_step](#3.4.2 sqlite3_step)
    • [3.5 查询结果读取 API(column 系列)](#3.5 查询结果读取 API(column 系列))
      • [3.5.1 sqlite3_column_text](#3.5.1 sqlite3_column_text)
    • [3.6 资源释放 API](#3.6 资源释放 API)
      • [3.6.1 sqlite3_finalize](#3.6.1 sqlite3_finalize)
  • [4 ~> 标准 C 代码示例](#4 ~> 标准 C 代码示例)
    • [4.1 数据库打开关闭示例](#4.1 数据库打开关闭示例)
    • [4.2 sqlite3_exec 创建表示例](#4.2 sqlite3_exec 创建表示例)
    • [4.3 prepare‑bind‑step‑finalize 完整流程(预处理插入)](#4.3 prepare‑bind‑step‑finalize 完整流程(预处理插入))
  • [5 ~> API 开发关键易错点总结](#5 ~> API 开发关键易错点总结)
  • [6 ~> 安全重点:SQL 注入防护](#6 ~> 安全重点:SQL 注入防护)
  • 结尾


1 ~> SQLite 基础概念

1.1 SQLite 存储类

SQLite 是弱类型数据库,存储类比声明的数据类型优先级更高,一条记录的每个字段可以拥有不同存储类型。

  • INTEGER:带符号整数,占用 1/2/3/4/6/8 字节,根据数值大小自动选择存储空间。
  • REAL:8 字节 IEEE754 双精度浮点。
  • TEXT:文本字符串,支持 UTF‑8、UTF‑16BE、UTF‑16LE 编码。
  • BLOB:原始二进制字节流,输入什么就存储什么,不做任何转换。
  • NULL:空值。

1.2 亲和类型 (Affinity)

亲和类型:建表时给列声明类型,插入数据时 SQLite 按照亲和规则对输入数据做隐式转换;不会强制限制存储类

1.2.1 五种亲和类型

  • TEXT:插入数值会先转为文本再存储;NULL、BLOB 不转换。
  • NUMERIC:文本插入时,如果转换为 INTEGER/REAL 无损可逆,则转换;否则保持 TEXT。"30000.0"可以无损转为整数时,存储为 INTEGER。NULL/BLOB 原样保存。
  • INTEGER:转换规则等价NUMERIC,区别仅在CAST强制类型转换表达式行为。
  • REAL:转换规则等价NUMERIC不会把 **"30000.0"**这类可转整数的文本转为 INTEGER,始终保存浮点
  • NONE:完全不做转换,输入是什么存储类就保存什么。

1.2.2 建表类型名与亲和类型映射

声明类型 亲和类型
INT、INTEGER、TINYINT、SMALLINT、MEDIUMINT、BIGINT、UNSIGNED BIG INT、INT2、INT8 INTEGER
CHARACTER(n)、VARCHAR(n)、TEXT TEXT

建表写的类型名仅用于推导亲和类型,不做严格类型约束,也不限制存储长度

1.3 SQLite 常用 SQL 语法分类

  • DML:DELETESELECTINSERTUPDATELIKEGLOBLIMITORDER BYGROUP BYHAVINGDISTINCT
  • DDL:CREATE TABLEALTERCREATE INDEXCREATE VIEWCREATE TRIGGER
  • 特殊语法:PRAGMAJOINUNIONNULL、别名、AutoincrementVACUUM、日期时间函数、内置聚合函数、EXPLAIN、SQL 注入防护

2 ~> SQLite C/C++ 开发环境

2.1 开发依赖

  1. 头文件:#include <sqlite3.h>,编译阶段依赖。
  2. 库文件:<libsqlite3.so/libsqlite3.a>,链接阶段依赖。

2.2 编译链接命令

2.2.1 GCC/G++ 命令

bash 复制代码
# C程序编译链接
gcc test.c -o test -lsqlite3

# C++程序编译链接
g++ test.cpp -o test -lsqlite3

2.2.2 Makefile

makefile 复制代码
my_program: main.cpp
	g++ main.cpp -o my_program -lsqlite3

2.2.3 CMakeLists.txt

cmake 复制代码
add_executable(my_program main.cpp)
target_link_libraries(my_program sqlite3)

3 ~> SQLite C API 核心模块

核心对象:

  • sqlite3*:数据库连接句柄
  • sqlite3_stmt*:预处理语句句柄(编译后的 SQL 字节码对象) 返回值宏:SQLITE_OK= 操作成功;其他均为错误码。

3.1 数据库连接管理 API

3.1.1 sqlite3_open

c 复制代码
int sqlite3_open(const char *filename, sqlite3 **ppDb);
  • 功能:打开 / 创建数据库文件,得到数据库连接句柄。
  • 参数
    • filename:数据库文件路径;传NULL或者"memory",创建内存数据库,会话结束数据全部销毁。文件不存在则自动创建空数据库文件。
    • ppDb:输出参数,二级指针;函数调用成功后写入 sqlite3 连接句柄。
  • 返回值:SQLITE_OK成功,错误码失败。

3.1.2 sqlite3_close

c 复制代码
int sqlite3_close(sqlite3* db);
  • 功能:关闭数据库连接,释放连接占用资源。
  • 约束:所有 sqlite3_stmt 预处理语句必须全部 finalize 销毁之后,才能正常 close ;仍有未完成预处理语句,返回SQLITE_BUSY,关闭失败。
  • 参数:数据库连接句柄db
  • 返回值:SQLITE_OK成功;SQLITE_BUSY繁忙。

3.1.3 sqlite3_errmsg

c 复制代码
const char *sqlite3_errmsg(sqlite3* db);
  • 功能:获取该连接上最近一次错误的英文错误描述字符串。
  • 参数:数据库连接句柄。
  • 返回值:只读字符串指针;下一次数据库调用会覆盖错误信息。

3.2 SQL 预处理编译 API(prepare‑v2)

3.2.1 sqlite3_prepare_v2

c 复制代码
int sqlite3_prepare_v2(
    sqlite3 *db,
    const char *zSql,
    int nByte,
    sqlite3_stmt **ppStmt,
    const char **pzTail
);
  • 功能:将 SQL 文本编译为 SQLite 虚拟机字节码,生成预处理语句对象sqlite3_stmt*仅编译,不会执行 SQL。会做 SQL 语法校验,语法非法直接返回错误码。
  • 参数
    • db:数据库连接句柄。
    • zSql:原始 SQL 字符串。
    • nByte:SQL 字节长度;传-1自动按\0计算字符串长度。
    • ppStmt:输出参数,得到预处理语句句柄。
    • pzTail:输出参数,SQL 字符串中未参与编译的剩余部分,业务代码几乎全部传NULL
  • 返回值:SQLITE_OK编译成功,错误码编译失败。

3.2.2 SQL 占位符(参数绑定)

预处理语句支持两种占位符,用于防 SQL 注入,复用编译后的字节码,循环批量插入效率极高。

  1. 问号占位符 ?:索引从1 开始
sql 复制代码
insert into student(name,gender,age,gap) values(?,?,?,?);
  1. 命名占位符 :varname
sql 复制代码
insert into student(name,gender,age,gap) values(:name,:gender,:age,:gap);

注意:绑定 API 的 index 参数从 1 开始计数 ;后续读取查询结果sqlite3_column_xxx列下标从 0 开始计数,极易混淆。

3.3 参数绑定 API(bind 系列)

bind 系列:给预处理语句占位符填充运行时数据;必须在sqlite3_step之前调用。

3.3.1 sqlite3_bind_int64

c 复制代码
int sqlite3_bind_int64(sqlite3_stmt* pStmt, int index, sqlite3_int64 value);
  • 功能:绑定 64 位整型数据到指定占位符。
  • 参数
    • pStmt:预处理语句句柄。
    • index:占位符序号,起始为 1
    • value:待绑定 64 位整数。
  • 返回值:SQLITE_OK绑定成功。

3.3.2 sqlite3_bind_text

c 复制代码
int sqlite3_bind_text(
    sqlite3_stmt* pStmt,
    int index,
    const char *value,
    int len,
    void(*destructor)(void*)
);
  • 功能:绑定字符串文本。
  • 参数
    • index:占位符序号,起始为 1
    • value:字符串指针。
    • len:字节长度;传-1自动识别\0
    • destructor:内存释放回调
      • SQLITE_STATIC:字符串内存由应用管理,SQLite 不会释放该内存。
      • SQLITE_TRANSIENT:SQLite 内部复制一份字符串副本,后续应用可以销毁原始字符串。
  • 返回值:SQLITE_OK绑定成功。

其他 bind 系列:sqlite3_bind_doublesqlite3_bind_blobsqlite3_bind_null

3.4 SQL 执行 API

3.4.1 sqlite3_exec

c 复制代码
int sqlite3_exec(
    sqlite3* db,
    const char *sql,
    int (*callback)(void*, int argc, char** argv, char** azColName),
    void *arg,
    char **errmsg
);
  • 功能:直接执行一条或多条 SQL 字符串,内部封装 prepare‑step‑finalize 整套流程。
  • 使用场景:适合无返回结果集 操作:CREATE TABLEINSERTDROP;也可以执行 SELECT,通过回调接收每行数据。
  • 参数
    • db:数据库连接。
    • sql:多条 SQL 拼接字符串。
    • callback:每行记录回调函数指针;不需要结果回调传NULL
      • arg:透传给 callback 第一个参数。
      • argc:当前行列数量。
      • argv[]:每一列的值字符串指针。
      • azColName[]:每一列字段名字符串指针。
    • errmsg:输出错误字符串指针;出错后必须调用sqlite3_free(*errmsg)释放内存。
  • 返回值:SQLITE_OK全部 SQL 执行成功。

3.4.2 sqlite3_step

c 复制代码
int sqlite3_step(sqlite3_stmt *pStmt);
  • 功能:推进、执行预处理语句;循环调用获取查询结果行。
  • 返回值
    • SQLITE_ROW:读到一行有效结果,此时可以调用sqlite3_column_xxx读取该行各列数据。
    • SQLITE_DONE:SQL 语句全部执行完毕,没有更多行。
    • 其他:错误码。

对于 SELECT 查询:循环调用sqlite3_step直到返回SQLITE_DONE,每一次返回SQLITE_ROW代表一行记录就绪。

3.5 查询结果读取 API(column 系列)

3.5.1 sqlite3_column_text

c 复制代码
const unsigned char *sqlite3_column_text(sqlite3_stmt* pStmt, int iCol);
  • 功能:读取当前 step 行指定列文本数据。
  • 参数:iCol列下标,从 0 开始计数
  • 返回值:只读 unsigned char 字符串指针;指针有效期截止到下一次sqlite3_step / sqlite3_finalize调用。

配套读取接口: sqlite3_column_intsqlite3_column_doublesqlite3_column_blobsqlite3_column_bytes

3.6 资源释放 API

3.6.1 sqlite3_finalize

c 复制代码
int sqlite3_finalize(sqlite3_stmt *pStmt);
  • 功能:销毁预处理语句对象,释放 stmt 对象全部资源。
  • 约束:所有 sqlite3_stmt 对象必须调用 finalize 释放,否则会造成资源泄露;close 之前必须全部 finalize 完成
  • 返回值:SQLITE_OK成功。

4 ~> 标准 C 代码示例

4.1 数据库打开关闭示例

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

int main(int argc, char* argv[])
{
    sqlite3 *db;
    int rc;

    /* 打开数据库,不存在则创建test.db */
    rc = sqlite3_open("test.db", &db);
    if (rc != SQLITE_OK)
    {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        exit(EXIT_FAILURE);
    }
    fprintf(stdout, "Opened database successfully\n");

    /* 业务操作... */

    /* 关闭数据库连接 */
    sqlite3_close(db);
    return 0;
}

4.2 sqlite3_exec 创建表示例

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

/* exec查询回调函数 */
static int callback(void *NotUsed, int argc, char** argv, char** azColName)
{
    int i;
    for(i = 0; i < argc; i++)
    {
        printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
    }
    printf("\n");
    return 0;
}

int main(int argc, char* argv[])
{
    sqlite3 *db;
    char *zErrMsg = NULL;
    int rc;
    const char* sql =
    "CREATE TABLE COMPANY("
    "ID INT PRIMARY KEY NOT NULL,"
    "NAME TEXT NOT NULL,"
    "AGE INT NOT NULL,"
    "ADDRESS CHAR(50),"
    "SALARY REAL);";

    rc = sqlite3_open("test.db", &db);
    if(rc != SQLITE_OK)
    {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        exit(EXIT_FAILURE);
    }

    /* 执行建表SQL */
    rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
    if(rc != SQLITE_OK)
    {
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }
    else
    {
        fprintf(stdout, "Table created successfully\n");
    }

    sqlite3_close(db);
    return 0;
}

4.3 prepare‑bind‑step‑finalize 完整流程(预处理插入)

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

int main(void)
{
    sqlite3 *db;
    sqlite3_stmt *stmt;
    int rc;
    const char* sql = "insert into student(name, gender, age, gap) values(?,?,?,?);";

    rc = sqlite3_open("test.db", &db);
    if(rc != SQLITE_OK)
    {
        fprintf(stderr, "open db failed: %s\n", sqlite3_errmsg(db));
        return 1;
    }

    /* 1.编译SQL生成预处理stmt */
    rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if(rc != SQLITE_OK)
    {
        fprintf(stderr, "prepare failed: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        return 1;
    }

    /* 2.绑定参数,index从1开始 */
    sqlite3_bind_text(stmt, 1, "zhangsan", -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 2, "male", -1, SQLITE_STATIC);
    sqlite3_bind_int64(stmt, 3, 18);
    sqlite3_bind_double(stmt, 4, 3.5);

    /* 3.执行 */
    rc = sqlite3_step(stmt);
    if(rc == SQLITE_DONE)
    {
        printf("insert ok\n");
    }
    else
    {
        fprintf(stderr, "step error: %s\n", sqlite3_errmsg(db));
    }

    /* 4.释放预处理语句资源 */
    sqlite3_finalize(stmt);
    sqlite3_close(db);
    return 0;
}

5 ~> API 开发关键易错点总结

  1. 索引两套规则极易混淆
    1. bind 绑定占位符序号:从 1 开始
    2. column 读取查询结果列号:从 0 开始
  2. 资源生命周期
    1. sqlite3_stmt必须调用sqlite3_finalize释放;未 finalize 直接sqlite3_close返回SQLITE_BUSY关闭失败。
    2. sqlite3_exec出错返回的errmsg必须使用sqlite3_free释放堆内存,不能直接 free。
  3. 两种执行 API 选型
    1. sqlite3_exec:适合一次性简单 SQL,适合 DDL、批量无返回 DML;多条 SQL 字符串一次性执行。
    2. prepare‑bind‑step‑finalize:适合循环批量插入、动态参数查询,有效防御 SQL 注入攻击,性能更好。
  4. sqlite3_bind_text的 destructor 参数
    1. SQLITE_STATIC:字符串生命周期长于 stmt,SQLite 不接管内存。
    2. SQLITE_TRANSIENT:SQLite 复制字符串副本,原始字符串可以立即释放。
  5. 内存数据库:sqlite3_open(":memory:", &db),会话结束数据全部丢失,不会落盘磁盘文件。
  6. SQLite 是弱类型数据库,列声明类型仅决定亲和转换规则,不强制限制字段存储类。

6 ~> 安全重点:SQL 注入防护

  • 禁止字符串拼接用户输入直接拼接进 SQL 语句。
  • 正确方案:使用sqlite3_prepare_v2预处理 + bind 绑定占位符参数,用户输入交给 bind 接口处理,自动转义。
c 复制代码
// 错误!拼接用户输入,存在SQL注入风险
char sql_buf[256];
sprintf(sql_buf, "select * from user where name = '%s'", user_input);

安全写法: 使用?占位符,sqlite3_bind_text绑定用户输入。


结尾

uu们,本文的内容到这里就全部结束了,艾莉丝在这里再次感谢您的阅读!

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| ### 艾莉丝努力练剑 C/C++ & Linux 底层探索者 | 一个正在努力练剑的技术博主 *** ** * ** *** 👀 【关注】 跟随我一起深耕技术领域,见证每一次成长。 ❤️ 【点赞】 让优质内容被更多人看见,让知识传递更有力量。 ⭐ 【收藏】 把核心知识点存好,在需要时随时查、随时用。 💬 【评论】 分享你的经验或疑问,评论区一起交流避坑! 不要忘记给博主"一键四连"哦! "今日练剑达成!" "技术之路难免有困惑,但同行的人会让前进更有方向。" |

结语:希望对学习Linux相关内容的uu有所帮助,不要忘记给博主"一键四连"哦!

往期回顾

【AI大模型接入SDK】SQLite数据库基础概述

🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡 ૮₍ ˶ ˊ ᴥ ˋ˶₎ა

相关推荐
QXWZ_IA1 小时前
道路巡检高危作业的自动化替代方案
人工智能·科技·安全
Hotchip_MEMS1 小时前
平板MEMS麦克风阵列如何赋能远程会议与远场拾音
人工智能·笔记·物联网·电脑·制造
正经教主1 小时前
【FDE系列】阶段2:Day 33:进阶查询 — 窗口函数与 CTE
人工智能·python·fde
张彦峰ZYF1 小时前
AI时代Java工程师能力地图:哪些会被替代,哪些更加值钱
人工智能·架构·被替代的不是岗位而是任务·生成成本塌陷,验证成本没降·上下文闭合度·可判定性、可逆性·责任可归属性
東隅已逝,桑榆非晚1 小时前
List(类函数学习)
c++·笔记·学习
棣廷1 小时前
初识OpenCV——疲劳检测
人工智能·opencv·目标检测
byte轻骑兵1 小时前
【BlueZ 】Linux 内核蓝牙子系统入门:hci_core 模块与 BlueZ 的交互
linux·人工智能·bluez·电脑蓝牙·嵌入式蓝牙
Dr_Fourier1 小时前
AWQ量化
c++·人工智能·pytorch·ai
Casbin开源社区1 小时前
OpenAgent 详解:单二进制自托管 AI Agent 平台,30+ 模型接入、RAG 知识库、MCP 工具调用与 Casbin 工具权限
人工智能·golang·开源