C++链接并操作嵌入式数据库SQLite

1. 简单介绍

SQLite是一个以C语言库形式发布的嵌入式数据库引擎。在C++项目中使用它,主要有两种方式:

  • 直接使用C API :这是最直接、最底层的方式。SQLite本身提供一个纯C语言编写的头文件(sqlite3.h)和库文件(如 sqlite3.lib, sqlite3.dlllibsqlite3.a, libsqlite3.so)。

    • 步骤

      1. 获取库文件:从SQLite官网下载预编译的二进制文件,或下载源码自行编译。

      2. 配置项目

        • 在项目中包含 sqlite3.h头文件。

        • 在链接器设置中,添加SQLite的库文件路径,并链接 sqlite3库。

      3. 代码中调用 :在C++代码中,可以直接调用SQLite的C API函数,如 sqlite3_open(), sqlite3_exec(), sqlite3_prepare_v2()等。由于C++兼容C,这种方式是原生支持的。

  • 使用C++封装库 :为了获得更符合C++编程习惯(如RAII、异常安全、面向对象)的接口,社区创建了许多C++封装库。一个流行且轻量级的选择是 SQLiteCpp。它包装了原始C API,提供了更现代、更安全的C++接口。

    • 步骤

      1. 获取库:通过包管理器(如vcpkg, conan)安装,或从GitHub获取源码。

      2. 包含头文件 :包含 SQLiteCpp.h

      3. 使用C++风格接口 :使用 SQLite::Database, SQLite::Statement等类进行操作,代码更简洁,资源管理更安全。

2. 基本操作流程

C++ 操作 SQLite 通常需要以下步骤:

1. 链接 SQLite 库

静态链接

复制代码
// 直接包含 sqlite3.c 源文件到项目中
#include "sqlite3.c"

// 编译时:g++ main.cpp -o app -lpthread -ldl

动态链接

cpp 复制代码
// 使用头文件和动态库
#include <sqlite3.h>

// 编译时:g++ main.cpp -o app -lsqlite3 -lpthread -ldl

各参数说明:

  • g++:C++ 编译器

  • main.cpp:你的源代码文件

  • -o app:指定输出可执行文件名为 app

  • -lsqlite3:链接 SQLite3 库

  • -lpthread:链接 POSIX 线程库

  • -ldl:链接动态加载库(Linux 上需要)

2. 示例

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

class SQLiteDB {
private:
    sqlite3* db;
    
public:
    SQLiteDB() : db(nullptr) {}
    
    // 打开数据库
    bool open(const std::string& filename) {
        int rc = sqlite3_open(filename.c_str(), &db);
        if (rc != SQLITE_OK) {
            std::cerr << "无法打开数据库: " << sqlite3_errmsg(db) << std::endl;
            return false;
        }
        return true;
    }
    
    // 执行 SQL 语句
    bool execute(const std::string& sql) {
        char* errMsg = nullptr;
        int rc = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, &errMsg);
        if (rc != SQLITE_OK) {
            std::cerr << "SQL 错误: " << errMsg << std::endl;
            sqlite3_free(errMsg);
            return false;
        }
        return true;
    }
    
    // 查询数据(回调函数方式)
    static int callback(void* data, int argc, char** argv, char** colName) {
        for (int i = 0; i < argc; i++) {
            std::cout << colName[i] << " = " << (argv[i] ? argv[i] : "NULL") << std::endl;
        }
        std::cout << "--------" << std::endl;
        return 0;
    }
    
    // 带参数的查询
    bool query(const std::string& sql) {
        char* errMsg = nullptr;
        int rc = sqlite3_exec(db, sql.c_str(), callback, nullptr, &errMsg);
        if (rc != SQLITE_OK) {
            std::cerr << "查询错误: " << errMsg << std::endl;
            sqlite3_free(errMsg);
            return false;
        }
        return true;
    }
    
    // 使用预处理语句(防SQL注入)
    bool preparedInsert(const std::string& name, int age) {
        sqlite3_stmt* stmt;
        const char* sql = "INSERT INTO users (name, age) VALUES (?, ?)";
        
        int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr);
        if (rc != SQLITE_OK) {
            return false;
        }
        
        // 绑定参数
        sqlite3_bind_text(stmt, 1, name.c_str(), -1, SQLITE_STATIC);
        sqlite3_bind_int(stmt, 2, age);
        
        // 执行
        rc = sqlite3_step(stmt);
        
        // 清理
        sqlite3_finalize(stmt);
        
        return rc == SQLITE_DONE;
    }
    
    // 关闭数据库
    void close() {
        if (db) {
            sqlite3_close(db);
            db = nullptr;
        }
    }
    
    ~SQLiteDB() {
        close();
    }
};

int main() {
    SQLiteDB database;
    
    // 打开数据库(如果不存在则创建)
    if (!database.open("test.db")) {
        return 1;
    }
    
    // 创建表
    database.execute("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)");
    
    // 插入数据
    database.execute("INSERT INTO users (name, age) VALUES ('张三', 25)");
    database.execute("INSERT INTO users (name, age) VALUES ('李四', 30)");
    
    // 使用预处理语句插入
    database.preparedInsert("王五", 28);
    
    // 查询数据
    std::cout << "查询结果:" << std::endl;
    database.query("SELECT * FROM users");
    
    // 更新数据
    database.execute("UPDATE users SET age = 26 WHERE name = '张三'");
    
    // 删除数据
    database.execute("DELETE FROM users WHERE age > 29");
    
    // 再次查询
    std::cout << "\n更新后的结果:" << std::endl;
    database.query("SELECT * FROM users");
    
    return 0;
}

3. 使用 C++ 封装库(简化复杂操作)

除了直接使用 C API,还可以使用 C++ 封装库:

SQLiteCpp(推荐)

复制代码
#include <SQLiteCpp/SQLiteCpp.h>
#include <iostream>

int main() {
    try {
        // 打开数据库
        SQLite::Database db("test.db", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
        
        // 执行 SQL
        db.exec("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)");
        
        // 插入数据
        SQLite::Statement insert(db, "INSERT INTO users (name, age) VALUES (?, ?)");
        insert.bind(1, "张三");
        insert.bind(2, 25);
        insert.exec();
        
        // 查询数据
        SQLite::Statement query(db, "SELECT * FROM users");
        while (query.executeStep()) {
            int id = query.getColumn(0);
            std::string name = query.getColumn(1);
            int age = query.getColumn(2);
            std::cout << "id: " << id << ", name: " << name << ", age: " << age << std::endl;
        }
        
    } catch (std::exception& e) {
        std::cerr << "SQLite 异常: " << e.what() << std::endl;
    }
    
    return 0;
}

4. 编译命令

直接编译:

复制代码
# 使用系统库
g++ main.cpp -o app -lsqlite3 -lpthread -ldl

# 使用 SQLiteCpp
g++ main.cpp -o app -lsqlite3 -lSQLiteCpp -lpthread -ldl

CMake 配置:

复制代码
cmake_minimum_required(VERSION 3.10)
project(SQLiteExample)

find_package(SQLite3 REQUIRED)
find_package(SQLiteCpp REQUIRED)  # 如果使用 SQLiteCpp

add_executable(app main.cpp)
target_link_libraries(app SQLite::SQLite3)
target_link_libraries(app SQLiteCpp)  # 如果使用 SQLiteCpp

5. 主要特点

  1. 零配置:无需服务器,单文件数据库

  2. 事务支持:ACID 兼容

  3. 跨平台:支持 Windows、Linux、macOS 等

  4. 轻量级:库文件小,资源占用少

  5. 丰富的 API :提供完整的 SQL 支持

    SQL = Structured Query Language(结构化查询语言))

6.与其他数据库的扩展名对比

数据库系统 常见扩展名 说明
SQLite .db, .sqlite, .sqlite3 单文件嵌入式数据库
MySQL .sql, .frm, .ibd 需要服务器,多文件
PostgreSQL 无特定扩展名 目录结构,无单文件
SQL Server .mdf, .ldf 微软数据库系统
Oracle .dbf, .ora 企业级数据库
**SQLite (加密)**​ .db, .sqlite 内容加密,扩展名相同
Access .mdb, .accdb 微软 Access 数据库
相关推荐
明月_清风7 分钟前
🚀 Flyway 存量数据库迁移:50张表一键导出清洗实战(附完整脚本)
数据库·后端
深邃-13 分钟前
【C语言】-数据在内存中的存储(1)
c语言·开发语言·数据结构·c++·算法
羊小蜜.15 分钟前
Mysql 08: 数据表基本操作——从创建到约束
数据库·mysql·数据表
程序员小郭8316 分钟前
MySQL分库分表策略全解析(实战版)
数据库·mysql·架构
卓怡学长18 分钟前
m320基于Java的网络音乐系统的设计与实现
java·数据库·spring·tomcat·maven
xiaoye-duck20 分钟前
《算法题讲解指南:优选算法-字符串》--61.最长公共前缀,62.最长回文子串,63.二进制求和,64.字符串相乘
c++·算法·字符串
chh56323 分钟前
从零开始学C++--类和对象
java·开发语言·c++·学习·算法
xyx-3v37 分钟前
C++构造函数、析构函数与拷贝控制深度解析
开发语言·c++
Larry_Yanan41 分钟前
Qt+OpenCV(一)环境搭建
开发语言·c++·qt·opencv·学习
爱浦路 IPLOOK42 分钟前
选对UPF网元供应商,解锁5G-A时代行业赋能新可能
运维·网络·数据库