Skip to content

SQLite的c++接口

安装

这里建议使用msys2进行安装,如果你使用的是vs编译c++程序也可以使用vcpkg进行安装。

C/C++ 接口 API

SQLite的C/C++接口提供了一系列的函数,可以用来操作数据库,包括创建数据库,创建表,插入数据,查询数据,更新数据,删除数据等。

实例

众所周知学习一个编程语言的最好方式就是通过实例来学习,下面我们就用C++来实现一个简单的数据库操作。

c++
#include <iostream>
#include <sqlite3.h> // SQLite头文件
#include <string>

// 数据库文件名
const char* DB_NAME = "test.db";

// 创建表格SQL语句
const char* CREATE_TABLE_SQL = 
    "CREATE TABLE IF NOT EXISTS users ("
    "id INTEGER PRIMARY KEY AUTOINCREMENT,"
    "name TEXT NOT NULL,"
    "age INTEGER,"
    "email TEXT);";

// 数据库连接句柄
sqlite3* db = nullptr;

// 连接数据库
bool connectDatabase() {
    int rc = sqlite3_open(DB_NAME, &db);
    if (rc != SQLITE_OK) {
        std::cerr << "无法打开数据库: " << sqlite3_errmsg(db) << std::endl;
        return false;
    }
    std::cout << "数据库连接成功!" << std::endl;
    return true;
}

// 关闭数据库连接
void disconnectDatabase() {
    if (db) {
        sqlite3_close(db);
        std::cout << "数据库连接已关闭" << std::endl;
    }
}

// 创建表格
bool createTable() {
    char* errMsg = nullptr;
    int rc = sqlite3_exec(db, CREATE_TABLE_SQL, nullptr, nullptr, &errMsg);
    if (rc != SQLITE_OK) {
        std::cerr << "创建表格失败: " << errMsg << std::endl;
        sqlite3_free(errMsg);
        return false;
    }
    std::cout << "表格创建/检测成功" << std::endl;
    return true;
}

// 插入数据
bool insertUser(const std::string& name, int age, const std::string& email) {
    const char* sql = "INSERT INTO users (name, age, email) VALUES (?, ?, ?);";
    sqlite3_stmt* stmt;
    
    // 准备预处理语句
    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr);
    if (rc != SQLITE_OK) {
        std::cerr << "准备插入语句失败: " << sqlite3_errmsg(db) << std::endl;
        return false;
    }

    // 绑定参数
    sqlite3_bind_text(stmt, 1, name.c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_int(stmt, 2, age);
    sqlite3_bind_text(stmt, 3, email.c_str(), -1, SQLITE_STATIC);

    // 执行语句
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE) {
        std::cerr << "执行插入失败: " << sqlite3_errmsg(db) << std::endl;
        sqlite3_finalize(stmt);
        return false;
    }

    std::cout << "插入数据成功,ID: " << sqlite3_last_insert_rowid(db) << std::endl;
    sqlite3_finalize(stmt);
    return true;
}

// 查询数据回调函数
static int selectCallback(void* data, int argc, char** argv, char** colName) {
    for (int i = 0; i < argc; i++) {
        std::cout << colName[i] << ": " << (argv[i] ? argv[i] : "NULL") << "\t";
    }
    std::cout << "\n";
    return 0;
}

// 查询所有用户
void selectAllUsers() {
    const char* sql = "SELECT * FROM users;";
    char* errMsg = nullptr;
    
    std::cout << "\n查询结果:" << std::endl;
    int rc = sqlite3_exec(db, sql, selectCallback, nullptr, &errMsg);
    if (rc != SQLITE_OK) {
        std::cerr << "查询失败: " << errMsg << std::endl;
        sqlite3_free(errMsg);
    }
}

// 更新用户信息
bool updateUser(int id, const std::string& newEmail) {
    const char* sql = "UPDATE users SET email = ? WHERE id = ?;";
    sqlite3_stmt* stmt;

    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr);
    if (rc != SQLITE_OK) {
        std::cerr << "准备更新语句失败: " << sqlite3_errmsg(db) << std::endl;
        return false;
    }

    sqlite3_bind_text(stmt, 1, newEmail.c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_int(stmt, 2, id);

    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE) {
        std::cerr << "执行更新失败: " << sqlite3_errmsg(db) << std::endl;
        sqlite3_finalize(stmt);
        return false;
    }

    std::cout << "更新影响行数: " << sqlite3_changes(db) << std::endl;
    sqlite3_finalize(stmt);
    return true;
}

// 删除用户
bool deleteUser(int id) {
    const char* sql = "DELETE FROM users WHERE id = ?;";
    sqlite3_stmt* stmt;

    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr);
    if (rc != SQLITE_OK) {
        std::cerr << "准备删除语句失败: " << sqlite3_errmsg(db) << std::endl;
        return false;
    }

    sqlite3_bind_int(stmt, 1, id);

    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE) {
        std::cerr << "执行删除失败: " << sqlite3_errmsg(db) << std::endl;
        sqlite3_finalize(stmt);
        return false;
    }

    std::cout << "删除影响行数: " << sqlite3_changes(db) << std::endl;
    sqlite3_finalize(stmt);
    return true;
}

int main() {
    // 连接数据库
    if (!connectDatabase()) return 1;

    // 创建表格
    if (!createTable()) {
        disconnectDatabase();
        return 1;
    }

    // 插入示例数据
    insertUser("张三", 25, "zhangsan@example.com");
    insertUser("李四", 30, "lisi@example.com");

    // 查询所有数据
    selectAllUsers();

    // 更新数据(假设第一条记录的ID是1)
    updateUser(1, "new_email@example.com");
    selectAllUsers();

    // 删除数据(假设要删除ID为2的记录)
    deleteUser(2);
    selectAllUsers();

    // 关闭数据库连接
    disconnectDatabase();
    return 0;
}

这很长对吧但是我们可以逐一击破

讲解实例

这段代码是一个使用 SQLite 数据库的 C++ 程序,主要功能包括连接数据库、创建表格、插入数据、查询数据、更新数据和删除数据。以下是对代码的详细解析:


1. 头文件与全局变量

cpp
#include <iostream>
#include <sqlite3.h> // SQLite头文件
#include <string>

// 数据库文件名
const char* DB_NAME = "test.db";

// 创建表格SQL语句
const char* CREATE_TABLE_SQL = 
    "CREATE TABLE IF NOT EXISTS users ("
    "id INTEGER PRIMARY KEY AUTOINCREMENT,"
    "name TEXT NOT NULL,"
    "age INTEGER,"
    "email TEXT);";

// 数据库连接句柄
sqlite3* db = nullptr;
  • sqlite3.h:SQLite 的头文件,提供了操作 SQLite 数据库的 API。
  • DB_NAME:数据库文件名,这里定义为 test.db
  • CREATE_TABLE_SQL:创建表格的 SQL 语句,定义了一个名为 users 的表格,包含 idnameageemail 四个字段。
  • sqlite3* db:数据库连接句柄,用于存储数据库连接对象。

2. 连接与关闭数据库

cpp
bool connectDatabase() {
    int rc = sqlite3_open(DB_NAME, &db);
    if (rc != SQLITE_OK) {
        std::cerr << "无法打开数据库: " << sqlite3_errmsg(db) << std::endl;
        return false;
    }
    std::cout << "数据库连接成功!" << std::endl;
    return true;
}

void disconnectDatabase() {
    if (db) {
        sqlite3_close(db);
        std::cout << "数据库连接已关闭" << std::endl;
    }
}
  • connectDatabase():连接数据库,使用 sqlite3_open 打开数据库文件。如果成功,返回 true;否则输出错误信息并返回 false
  • disconnectDatabase():关闭数据库连接,使用 sqlite3_close 释放资源。

3. 创建表格

cpp
bool createTable() {
    char* errMsg = nullptr;
    int rc = sqlite3_exec(db, CREATE_TABLE_SQL, nullptr, nullptr, &errMsg);
    if (rc != SQLITE_OK) {
        std::cerr << "创建表格失败: " << errMsg << std::endl;
        sqlite3_free(errMsg);
        return false;
    }
    std::cout << "表格创建/检测成功" << std::endl;
    return true;
}
  • createTable():执行 SQL 语句创建表格。如果表格已存在,则不会重复创建。
  • sqlite3_exec():执行 SQL 语句的函数。如果执行失败,会通过 errMsg 返回错误信息。

4. 插入数据

cpp
bool insertUser(const std::string& name, int age, const std::string& email) {
    const char* sql = "INSERT INTO users (name, age, email) VALUES (?, ?, ?);";
    sqlite3_stmt* stmt;
  
    // 准备预处理语句
    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr);
    if (rc != SQLITE_OK) {
        std::cerr << "准备插入语句失败: " << sqlite3_errmsg(db) << std::endl;
        return false;
    }

    // 绑定参数
    sqlite3_bind_text(stmt, 1, name.c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_int(stmt, 2, age);
    sqlite3_bind_text(stmt, 3, email.c_str(), -1, SQLITE_STATIC);

    // 执行语句
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE) {
        std::cerr << "执行插入失败: " << sqlite3_errmsg(db) << std::endl;
        sqlite3_finalize(stmt);
        return false;
    }

    std::cout << "插入数据成功,ID: " << sqlite3_last_insert_rowid(db) << std::endl;
    sqlite3_finalize(stmt);
    return true;
}
  • insertUser():插入一条用户数据。
  • sqlite3_prepare_v2():准备 SQL 语句,返回一个 sqlite3_stmt 对象。
  • sqlite3_bind_*():绑定参数到预处理语句中。
  • sqlite3_step():执行预处理语句。
  • sqlite3_last_insert_rowid():获取最后插入行的 ID。

5. 查询数据

cpp
static int selectCallback(void* data, int argc, char** argv, char** colName) {
    for (int i = 0; i < argc; i++) {
        std::cout << colName[i] << ": " << (argv[i] ? argv[i] : "NULL") << "\t";
    }
    std::cout << "\n";
    return 0;
}

void selectAllUsers() {
    const char* sql = "SELECT * FROM users;";
    char* errMsg = nullptr;
  
    std::cout << "\n查询结果:" << std::endl;
    int rc = sqlite3_exec(db, sql, selectCallback, nullptr, &errMsg);
    if (rc != SQLITE_OK) {
        std::cerr << "查询失败: " << errMsg << std::endl;
        sqlite3_free(errMsg);
    }
}
  • selectCallback():查询结果的回调函数,用于逐行处理查询结果。
  • selectAllUsers():查询所有用户数据,使用 sqlite3_exec 执行查询,并通过回调函数输出结果。

6. 更新数据

cpp
bool updateUser(int id, const std::string& newEmail) {
    const char* sql = "UPDATE users SET email = ? WHERE id = ?;";
    sqlite3_stmt* stmt;

    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr);
    if (rc != SQLITE_OK) {
        std::cerr << "准备更新语句失败: " << sqlite3_errmsg(db) << std::endl;
        return false;
    }

    sqlite3_bind_text(stmt, 1, newEmail.c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_int(stmt, 2, id);

    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE) {
        std::cerr << "执行更新失败: " << sqlite3_errmsg(db) << std::endl;
        sqlite3_finalize(stmt);
        return false;
    }

    std::cout << "更新影响行数: " << sqlite3_changes(db) << std::endl;
    sqlite3_finalize(stmt);
    return true;
}
  • updateUser():更新指定用户的邮箱。
  • sqlite3_changes():返回受更新操作影响的行数。

7. 删除数据

cpp
bool deleteUser(int id) {
    const char* sql = "DELETE FROM users WHERE id = ?;";
    sqlite3_stmt* stmt;

    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr);
    if (rc != SQLITE_OK) {
        std::cerr << "准备删除语句失败: " << sqlite3_errmsg(db) << std::endl;
        return false;
    }

    sqlite3_bind_int(stmt, 1, id);

    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE) {
        std::cerr << "执行删除失败: " << sqlite3_errmsg(db) << std::endl;
        sqlite3_finalize(stmt);
        return false;
    }

    std::cout << "删除影响行数: " << sqlite3_changes(db) << std::endl;
    sqlite3_finalize(stmt);
    return true;
}
  • deleteUser():删除指定 ID 的用户。

8. 主函数

cpp
int main() {
    // 连接数据库
    if (!connectDatabase()) return 1;

    // 创建表格
    if (!createTable()) {
        disconnectDatabase();
        return 1;
    }

    // 插入示例数据
    insertUser("张三", 25, "zhangsan@example.com");
    insertUser("李四", 30, "lisi@example.com");

    // 查询所有数据
    selectAllUsers();

    // 更新数据(假设第一条记录的ID是1)
    updateUser(1, "new_email@example.com");
    selectAllUsers();

    // 删除数据(假设要删除ID为2的记录)
    deleteUser(2);
    selectAllUsers();

    // 关闭数据库连接
    disconnectDatabase();
    return 0;
}
  • main():程序的入口函数,依次执行连接数据库、创建表格、插入数据、查询数据、更新数据和删除数据等操作。

9. 总结

  • 这段代码展示了如何使用 SQLite 数据库进行基本的 CRUD(增删改查)操作。
  • 使用了预处理语句(sqlite3_prepare_v2)来防止 SQL 注入。
  • 通过回调函数处理查询结果。
  • 代码结构清晰,适合初学者学习 SQLite 的基本用法。

函数列表

以下是 SQLite3 中核心函数的分类和通俗讲解,帮助你快速理解它们的用途和使用场景。(由于 SQLite3 函数库庞大,这里列举常用核心函数)


一、数据库连接与关闭

1. sqlite3_open()

  • 作用:打开一个数据库文件,建立连接。
  • 参数
    • 数据库文件名(如 "test.db")。
    • 指向 sqlite3* 的指针,用于保存连接句柄。
  • 示例
    cpp
    sqlite3* db;
    int rc = sqlite3_open("test.db", &db); // 打开数据库
    if (rc != SQLITE_OK) {
        std::cerr << "打开失败!";
    }

2. sqlite3_close()

  • 作用:关闭数据库连接,释放资源。
  • 参数sqlite3* 连接句柄。
  • 示例
    cpp
    sqlite3_close(db); // 关闭连接

二、执行 SQL 语句

1. sqlite3_exec()

  • 作用:直接执行 SQL 语句(适合简单操作,如建表、插入)。
  • 参数
    • SQL 语句字符串。
    • 回调函数(处理查询结果)。
    • 回调函数的参数。
    • 错误信息指针。
  • 示例
    cpp
    const char* sql = "CREATE TABLE users (id INTEGER, name TEXT);";
    char* errmsg;
    int rc = sqlite3_exec(db, sql, nullptr, nullptr, &errmsg);
    if (rc != SQLITE_OK) {
        std::cerr << "错误: " << errmsg;
        sqlite3_free(errmsg);
    }

2. sqlite3_prepare_v2()

  • 作用:将 SQL 语句编译为预处理语句(防止 SQL 注入,适合复杂操作)。
  • 参数
    • SQL 语句字符串。
    • 输出预处理语句句柄 sqlite3_stmt**
  • 示例
    cpp
    const char* sql = "SELECT * FROM users WHERE id = ?;";
    sqlite3_stmt* stmt;
    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr);

3. sqlite3_step()

  • 作用:执行预处理语句,并逐行获取结果。
  • 返回值
    • SQLITE_ROW:表示有数据行可用。
    • SQLITE_DONE:表示执行完成(如插入、更新操作)。
  • 示例
    cpp
    while (sqlite3_step(stmt) == SQLITE_ROW) {
        // 读取数据
        int id = sqlite3_column_int(stmt, 0);
    }

4. sqlite3_finalize()

  • 作用:释放预处理语句占用的资源。
  • 示例
    cpp
    sqlite3_finalize(stmt); // 释放预处理语句

三、参数绑定与数据读取

1. 绑定参数函数

  • 作用:向预处理语句中的占位符 ? 绑定具体值。
  • 常用函数
    • sqlite3_bind_int(stmt, 位置, 值)
    • sqlite3_bind_text(stmt, 位置, 字符串, 长度, 释放方式)
  • 示例
    cpp
    sqlite3_bind_int(stmt, 1, 100);   // 绑定 id=100
    sqlite3_bind_text(stmt, 2, "Alice", -1, SQLITE_STATIC);

2. 读取结果函数

  • 作用:从查询结果的当前行中读取数据。
  • 常用函数
    • sqlite3_column_int(stmt, 列索引)
    • sqlite3_column_text(stmt, 列索引)
  • 示例
    cpp
    int id = sqlite3_column_int(stmt, 0);     // 读取第1列(整数)
    const char* name = (const char*)sqlite3_column_text(stmt, 1); // 读取第2列(字符串)

四、实用工具函数

1. sqlite3_last_insert_rowid()

  • 作用:获取最后插入行的自增 ID。
  • 示例
    cpp
    int lastId = sqlite3_last_insert_rowid(db);

2. sqlite3_changes()

  • 作用:返回最近一次操作(如更新、删除)影响的行数。
  • 示例
    cpp
    int rows = sqlite3_changes(db); // 更新/删除了多少行

3. sqlite3_errmsg()

  • 作用:获取最近一次错误的描述信息。
  • 示例
    cpp
    std::cerr << "错误: " << sqlite3_errmsg(db);

五、事务控制

1. BEGIN TRANSACTIONCOMMIT

  • 作用:手动控制事务(SQL 语句,非直接函数)。
  • 示例
    cpp
    sqlite3_exec(db, "BEGIN TRANSACTION;", nullptr, nullptr, nullptr);
    // 执行多个操作...
    sqlite3_exec(db, "COMMIT;", nullptr, nullptr, nullptr);

六、总结

核心函数使用场景

场景使用的函数
打开/关闭数据库sqlite3_open(), sqlite3_close()
执行简单 SQL 语句sqlite3_exec()
执行复杂/安全 SQL 语句sqlite3_prepare_v2(), sqlite3_step()
绑定参数sqlite3_bind_*()
读取结果sqlite3_column_*()
错误处理sqlite3_errmsg()

通俗理解

  • 预处理语句:像一个填空题模板,先写好 SQL 语句框架(如 SELECT * FROM users WHERE id = ?),再用 sqlite3_bind_*() 填入具体值,安全高效。
  • 回调函数:适合简单的查询,每次读到一行数据就自动调用回调函数处理。
  • 事务:把多个操作打包,要么全部成功,要么全部失败(比如转账操作)。