【AI大模型接入SDK】 —— SQLite上手

🌈欢迎来到实战项目专栏 ~~ 从零实现AI大模型接入SDK

AI大模型接入SDK

🌏持久化存储

🌏SQLite使用

SQLite是一个开源、轻量级、零配置、无服务器、自包含、事务性、支持标准SQL、跨平台的数据库管理系统

ubuntuSQLite命令行和开发库安装

cpp 复制代码
sudo apt install sqlite3 # 安装 sqlite3 命令⾏⼯具
sudo apt install libsqlite3-dev # 安装 sqlite 开发包
dpkg -L libsqlite3-dev # 列出已安装的 libsqlite3-dev 软件包所包含的所有⽂件及其安
装路径

编译时链接 sqlite3

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

CMakelists.txt:
target_link_libraries(${SDK_NAME} sqlite3)

🔥终端使用介绍

1️⃣常用命令

数据库操作命令:

SQLite支持列的亲和类型概念。任何列仍然可以存储任何类型的数据,当数据插入时,该字段的数据将会优先采用亲缘类型作为该值的存储方式。SQLite目前的版本支持以下五种亲缘类型:

在创建好表之后,sqlite会根据每个列的数据类型自动生成亲和类型

cpp 复制代码
create table test{
	a INT   ---亲和类型:INTEGER
	b TEXT  ---亲和类型:TEXT
}

在插入数据的时候,sqlite会根据实际插入的数据,结合亲和类型来确定实际在磁盘上的存储类

c 复制代码
insert into values("123",456)
  • 对于a列INT :实际插入的数据是"123"字符串,亲和类型是INTEGER,所以"123"字符串会被转化成整形数据123
  • 对于b列TEXT:实际插入的数据456整形数据,亲和类型为TEXT,456会被转化成字符串"456"

我们在定义数据表的时候,只需要知道这一列要存储什么类型的数据,把这个数据给好就行 ------ 不需要管存储类型与亲和类型(sqlite内部设置)

sqlite会根据偏好设置亲和类型,实际的存储类型取决于偏好类型转化规则

2️⃣使用演示

cpp 复制代码
> sqlite3        # 打开 sqlite 命令⾏⼯具
.help            # 查看帮助信息
.open student.db # 创建student数据库,数据库⽂件名称为student.db
.databases       # 验证数据库。检查当前连接了哪些数据库,以及数据库的详细状态信息
.tables          # 查看所有表

sqlite> CREATE TABLE student(   #创建学⽣表
(x1...> stuid INTEGER PRIMARY KEY AUTOINCREMENT,
(x1...> name TEXT NOT NULL,
(x1...> age INTEGER,
(x1...> score REAL
(x1...> );

INSERT INTO students(name, age, score) VALUES  # students中插⼊数据
...> ('张三', 18, 92.0),
...> ('李四', 19, 93.5),
...> ('王五', 18, 76.5);

select * from student;   # 查看学⽣信息
1|张三|92.0
2|李四|100.0
3|卢本伟|99.1
	
DELETE FROM student WHERE score < 95;   //删除小于95分的同学
select * from student; 
2|李四|100.0
3|卢本伟|99.1

🔥常用api介绍

包含头文件 #include <sqlite3.h>

数据库连接管理:

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

功能打开一个数据库连接。如果数据库件不存在,则创建它

  • 参数:filename - 数据库文件的路径
  • ppDb:⼀个指向sqlite3*的指针。函数成功后会在这个指针里填入数据库连接句柄

返回值:SQLITE_OK 表示创建成功,否则为错误码

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

功能 :关闭打开的数据库连接,并释放所有资源

参数:要关闭的数据库连接句柄

返回值:SQLITE_OK表示成功,如果还有未完成的预处理语句

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

功能获取与数据库连接相关的最后一次错误操作的英文描述字符串 。在操作失败后调用它来获取错误原因

参数db数据库连接句柄

返回值指向错误信息字符串的指针 。如果还有查询没有完成,将返回SQLITE_BUSY禁止关闭的错误消息

SQL语句预处理:

sqlite3_prepare_v2函数会对输入的SQL语句进行语法检测 ,如果语法有问题会立马返回错误码;如果语法正确,会将SQL编译成字节码 (给SQLite的虚拟机执行的形式)编译完成后,该函数会创建一个sqlite3_stmt 的结构,将编译的结构存储在该对象里

cpp 复制代码
int sqlite3_prepare_v2( sqlite3 *db,const char *zSql,int nByte,
                        sqlite3_stmt **ppStmt,const char **pzTail);

功能 :将⼀条SQL语句编译成一个预处理语句对象,为执行和绑定参数做准备

参数

  • db数据库连接句柄
  • zSql:要编译的SQL语句文本
  • nByteSQL文本的长度 (字节),-1表示自动计算到\0结束
  • ppStmt:指向sqlite3_stmt*的指针,表示输出预处理结果语句的句柄
  • pzTail:指向未使用的SQL部分指针,通常置为NULL

返回值编译成功返回SQLITE_K,否则返回错误码

c 复制代码
int sqlite3_bind_int64(sqlite3_stmt*, int index, sqlite3_int64 value);

功能 :向预处理语句中的指定参数位置绑定一个64位的整数值

参数:

  • index - 参数的序号,从1开始
  • value - 要绑定的整数值

返回值:SQLITE_OK表示绑定成功,否则为错误码

cpp 复制代码
int sqlite3_bind_text(sqlite3_stmt*, int index, const char *value, int len, void(*destructor)(void*));

功能 :向预处理语句的指定参数位置绑定⼀个文本字符串

参数:

  • index - 参数的序号,从1开始
  • value - 要绑定的文本字符串
  • len - 字符串的长度 (字节),-1表示自动计算到\0结束
  • destructor用于指定SQLite不会尝试释放该字符串
    • SQLITE_STATIC:SQLite不会尝试释放该字符串
    • SQLITE_TRANSIENT:SQLite会制作该字符串的副本,对副本进行操作

返回值:SQLITE_OK表示绑定成功,否则为错误码

执行语句

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

功能:执行一条或多条SQL语句,适合不返回数据的语句,如CREATE、INSERT

参数

  • db - 数据库连接句柄
  • sql - 要执行的SQL语句字符串
  • callback回调函数,每有⼀条结果记录就产生⼀次调用,可以设置为NULL
  • arg传递给回调函数的第一个参数
  • errmsg:指向错误信息的指针。必须由用户自己sqlite3_free释放

返回值:执行成功返回SQLITE_OK,否则返回错误码

c 复制代码
int sqlite3_step(sqlite3_stmt *pStmt);

功能用于逐步执行预处理语句。⼀般用于执行查询和更新操作,并返回执行结果。对于查询操作,sqlite3_step 需要多次调用,直到返回 SQLITE_DONE

参数pstmt - 预处理语句句柄

返回值:

  • SQLITE_ROW - 表示有一行结果数据就绪
  • SQLITE_DONE - 表示语句执行完成
  • 否则表示有其他错误
c 复制代码
const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);

功能:从当前结果行中,以const unsigned cht*的形式获取指定文本列的值

参数iCol表示列号,从0开始

返回值指向文本数据的指针

c 复制代码
int sqlite3_finalize(sqlite3_stmt *pStmt);

功能:销毁预处理语句对象,释放所有关联资源

参数:pstmt - 要销毁的预处理语句句柄

返回值:成功返回SQLITE_OK,否则为错误码

🔥使用案例

下面持久化存储学生信息,学生基本信息包括学号、姓名、性别、年龄、学分

增删查改的实现思路如下:

  • SQL语句

  • SQL语句进行编译,生成一个预处理语句

  • 绑定参数

  • 执行SQL语句

  • 最后清理stmt指针

cpp 复制代码
#include <cstddef>
#include <sqlite3.h>
#include <string>
#include <iostream>

struct StudentInfo {
    std::string name;
    std::string gender;
    int age;
    double gap;
};

class StudentDB{
public:
    StudentDB(const std::string& db_name) 
    {
        //创建并打开数据库
        int rc = sqlite3_open(db_name.c_str(), &db);
        if (rc != SQLITE_OK) {
            std::cerr << "Failed to open database: " << sqlite3_errmsg(db) << std::endl;
            sqlite3_close(db);
        }

        //初始化数据库表 ------ 创建学生信息表
        if(!initDataBase()) {
            sqlite3_close(db);
        }
    }

    ~StudentDB() 
    {
        if (db != nullptr)
            sqlite3_close(db);
    }

    //插入学生信息
    bool insertStudent(const StudentInfo& studentInfo) 
    {
        //VALUES 是一个占位符,表示将要插入的值
        std::string insertSQL = R"(
            INSERT INTO students (name, gender, age, gap) 
            VALUES (?, ?, ?, ?);           
        )";

        //对SQL语句进行编译,生成一个预处理语句 
        sqlite3_stmt* stmt = nullptr;
        int rc = sqlite3_prepare_v2(db, insertSQL.c_str(), -1, &stmt, nullptr);
        if (rc != SQLITE_OK) {
            std::cerr << "Failed to prepare statement: " << sqlite3_errmsg(db) << std::endl;
            return false;
        }
        // 绑定参数
        sqlite3_bind_text(stmt, 1, studentInfo.name.c_str(), -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(stmt, 2, studentInfo.gender.c_str(), -1, SQLITE_TRANSIENT);
        sqlite3_bind_int(stmt, 3, studentInfo.age);
        sqlite3_bind_int64(stmt, 4, studentInfo.gap);

        //执行SQL语句
        rc = sqlite3_step(stmt);
        if (rc != SQLITE_DONE) {
            std::cerr << "Failed to insert student: " << sqlite3_errmsg(db) << std::endl;
            return false;
        }

        //清理
        sqlite3_finalize(stmt);
        return true;
    }

    //查询学生信息
    bool queryStudent(const std::string& name) 
    {
        std::string querySQL = R"(
            SELECT * FROM students 
            WHERE name = ?;
        )";
        
        //准备SQL语句
        sqlite3_stmt* stmt = nullptr;
        int rc = sqlite3_prepare_v2(db, querySQL.c_str(), -1, &stmt, nullptr);
        if (rc != SQLITE_OK) {
            std::cerr << "Failed to prepare statement: " << sqlite3_errmsg(db) << std::endl;
            return false;
        }
        //绑定参数
        sqlite3_bind_text(stmt, 1, name.c_str(), -1, SQLITE_TRANSIENT);

        //执行SQL语句
        rc = sqlite3_step(stmt);
        if (rc != SQLITE_ROW) {
            std::cerr << "Failed to query student: " << sqlite3_errmsg(db) << std::endl;
            return false;
        }

        //提取出结果
        int stuid = sqlite3_column_int(stmt, 0);
        std::string stuName = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));  //sqlite3_column_text返回一个const unsigned char*,强转成const char*
        std::string gender = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2));  //sqlite3_column_text返回一个const unsigned char*,强转成const char*
        int age = sqlite3_column_int(stmt, 3);
        double gap = sqlite3_column_double(stmt, 4);

        std::cout << "查询到的学生信息如下:" << std::endl;
        std::cout << "Student ID: " << stuid << std::endl;
        std::cout << "Name: " << stuName << std::endl;
        std::cout << "Gender: " << gender << std::endl;
        std::cout << "Age: " << age << std::endl;
        std::cout << "Gap: " << gap << std::endl;

        //清理
        sqlite3_finalize(stmt);
        return true;
    }

    bool queryAllStudents() 
    {
        //查询所有学生信息
        std::string querySQL = R"(
            SELECT * FROM students;
        )";

        //准备SQL语句
        sqlite3_stmt* stmt = nullptr;
        int rc = sqlite3_prepare_v2(db, querySQL.c_str(), -1, &stmt, nullptr);
        if (rc != SQLITE_OK) {
            std::cerr << "Failed to prepare statement: " << sqlite3_errmsg(db) << std::endl;
            return false;
        }
        
        //不需要绑定参数 ------ 直接提取
        std::cout << "--------------所有学生信息如下 ---------------" << std::endl;
        while (sqlite3_step(stmt) == SQLITE_ROW) {
            //提取出结果
            int stuid = sqlite3_column_int(stmt, 0);
            std::string name = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
            std::string gender = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2));
            int age = sqlite3_column_int(stmt, 3);
            double gap = sqlite3_column_double(stmt, 4);

            //输出结果
            std::cout << "查询到的学生信息如下:" << std::endl;
            std::cout << "Student ID: " << stuid << 
                         " Name: " << name << 
                         " Gender: " << gender << 
                         " Age: " << age << 
                         " Gap: " << gap << std::endl;
            std::cout << "-----------------------------------------" << std::endl;
        }
        //检测是否还有数据
        if (sqlite3_step(stmt) != SQLITE_DONE) {
            std::cerr << "Failed to query all students: " << sqlite3_errmsg(db) << std::endl;
            return false;
        }
        sqlite3_finalize(stmt);
        return true;
    }

    //修改学生信息
    bool updateStudent(const std::string& name, const StudentInfo& studentInfo) 
    {
        std::string updateSQL = R"(
            UPDATE students 
            SET name = ?, gender = ?, age = ?, gap = ? 
            WHERE name = ?;
        )";

        //准备SQL语句
        sqlite3_stmt* stmt = nullptr;
        int rc = sqlite3_prepare_v2(db, updateSQL.c_str(), -1, &stmt, nullptr);
        if (rc != SQLITE_OK) {
            std::cerr << "Failed to prepare statement: " << sqlite3_errmsg(db) << std::endl;
            return false;
        }
        
        //绑定参数
        sqlite3_bind_text(stmt, 1, studentInfo.name.c_str(), -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(stmt, 2, studentInfo.gender.c_str(), -1, SQLITE_TRANSIENT);
        sqlite3_bind_int(stmt, 3, studentInfo.age);
        sqlite3_bind_int64(stmt, 4, studentInfo.gap);
        sqlite3_bind_text(stmt, 5, name.c_str(), -1, SQLITE_TRANSIENT);

        //执行SQL语句
        rc = sqlite3_step(stmt);
        if (rc != SQLITE_DONE) {
            std::cerr << "Failed to update student: " << sqlite3_errmsg(db) << std::endl;
            return false;
        }
        //执行成功,清理stmt
        sqlite3_finalize(stmt);
        return true;
    }

    //删除学生信息
    bool deleteStudent(const std::string& name) 
    {
        std::string deleteSQL = R"(
            DELETE FROM students 
            WHERE name = ?;
        )";

        //准备SQL语句
        sqlite3_stmt* stmt = nullptr;
        int rc = sqlite3_prepare_v2(db, deleteSQL.c_str(), -1, &stmt, nullptr);
        if (rc != SQLITE_OK) {
            std::cerr << "Failed to prepare statement: " << sqlite3_errmsg(db) << std::endl;
            return false;
        }
        //绑定参数
        sqlite3_bind_text(stmt, 1, name.c_str(), -1, SQLITE_TRANSIENT);

        //执行SQL语句
        rc = sqlite3_step(stmt);
        if (rc != SQLITE_DONE) {
            std::cerr << "Failed to delete student: " << sqlite3_errmsg(db) << std::endl;
            return false;
        }

        //清理
        sqlite3_finalize(stmt);
        return true;
    }
    
private:
    bool initDataBase() 
    {
        const std::string createTableSQL = R"(
            CREATE TABLE IF NOT EXISTS students (
                stuid INTEGER PRIMARY KEY AUTOINCREMENT,
                name TEXT,
                gender TEXT,
                age INTEGER,
                gap REAL);
            )";

        int rc = sqlite3_exec(db, createTableSQL.c_str(), nullptr, nullptr, nullptr);
        if (rc != SQLITE_OK) {
            std::cerr << "Failed to create table: " << sqlite3_errmsg(db) << std::endl;
            return false;
        }
        return true;
    }
    
private:
    sqlite3* db = nullptr;
};

int main()
{
    return 0;
}
cpp 复制代码
int main()
{
    StudentInfo student1("张三", "男", 18, 4.5);
    StudentInfo student2("李四", "女", 19, 3.5);
    StudentInfo student3("王五", "男", 20, 2.5);
    StudentInfo student4("赵六", "女", 21, 5.0);

    StudentDB db("students.db");
    db.insertStudent(student1);
    db.insertStudent(student2);
    db.insertStudent(student3);
    db.insertStudent(student4);

    //查询所有学生信息
    db.queryAllStudents();

    //修改学生张三的年龄和绩点
    student1.age = 35;
    student1.gap = 5.0;
    db.updateStudent("张三", student1);

    //查询指定学生信息
    db.queryStudent(student1.name);

    //删除学生
    db.deleteStudent(student2.name);
    db.queryAllStudents();

    return 0;
}

接下来进行编译看看是否能实现?

📢写在最后

接下来登场的是 数据管理

相关推荐
AI深栈1 小时前
第 9 章 · Model Context Protocol(MCP)
java·人工智能
陈嘿萌1 小时前
ECCV 2026|MAVFusion:运动感知稀疏交互驱动的高效红外-可见光视频融合
人工智能·计算机视觉·图像融合·佛山大学·学术研究与理论基础·eccv2026
俊哥V1 小时前
每日 AI 研究简报 · 2026-09-14
人工智能·ai
529宝宝起名网1 小时前
用 Python 实现基于字源特征的名字文化评分算法:从六书部首到文化寓意的多维度评分模型
python
孙启超1 小时前
【AI开发之Rust】第 5 课:引用与生命周期 —— 借用能活多久?
人工智能·后端·rust·llm·ai应用开发
努力学习的代码小白1 小时前
mem0源码学习03
python
码流子1 小时前
2026 图像数据标注工具横评:LabelImg / CVAT / Label Studio / X-AnyLabeling / 国产Web平台,到底怎么选?
大数据·人工智能·算法
hansang_IR1 小时前
【题解】[JSOI2016] 最佳团体(分数规划)
c++·算法
必须会一定会1 小时前
LiTwin 任务004:JSON Schema、OpenAPI、TypeScript、Java DTO 质量门禁实现
人工智能·程序人生·ai编程