1. 首页 > sqlite教程 > 正文

sqlite教程FG010-C/C++核心API与嵌入式开发入门

本文档风哥主要介绍sqlite数据库C/C++核心API与嵌入式开发相关知识,包括sqlite数据库C/C++ API概述、核心API详解、嵌入式开发基础等内容,风哥教程参考sqlite官方文档C/C++ Interface等内容编写,适合DBA人员和开发人员在学习和测试中使用,如果要应用于生产环境则需要自行确认。

Part01-基础概念与理论知识

1.1 sqlite数据库C/C++ API概述

sqlite提供了完整的C/C++ API,是嵌入式数据库开发的核心接口。更多视频教程www.fgedu.net.cn

1.1.1 sqlite数据库API特点

sqlite数据库C/C++ API特点:

1. 设计特点
├── 简洁高效
├── 面向对象风格
├── 错误码返回机制
└── 资源需要手动释放

2. 核心对象
├── sqlite3:数据库连接对象
├── sqlite3_stmt:预编译语句对象
├── sqlite3_value:值对象
└── sqlite3_context:函数上下文

3. 核心函数分类
├── 连接管理:打开、关闭数据库
├── 语句执行:准备、执行、销毁
├── 数据绑定:参数绑定
├── 结果获取:列值获取
└── 事务控制:事务管理

4. 头文件
#include <sqlite3.h>

5. 编译链接
gcc -o app app.c -lsqlite3

API使用流程:
┌─────────────────────────────────────────┐
│ 1. sqlite3_open() 打开数据库连接 │
│ 2. sqlite3_prepare() 准备SQL语句 │
│ 3. sqlite3_bind_*() 绑定参数 │
│ 4. sqlite3_step() 执行语句 │
│ 5. sqlite3_column_*()获取结果 │
│ 6. sqlite3_finalize()释放语句 │
│ 7. sqlite3_close() 关闭连接 │
└─────────────────────────────────────────┘

1.1.2 sqlite数据库错误处理

sqlite数据库错误码:

基本错误码:
├── SQLITE_OK (0):成功
├── SQLITE_ERROR (1):一般错误
├── SQLITE_BUSY (5):数据库忙
├── SQLITE_LOCKED (6):数据库锁定
├── SQLITE_NOMEM (7):内存不足
├── SQLITE_READONLY (8):只读数据库
├── SQLITE_INTERRUPT (9):操作中断
├── SQLITE_IOERR (10):IO错误
├── SQLITE_CORRUPT (11):数据库损坏
├── SQLITE_NOTFOUND (12):未找到
├── SQLITE_FULL (13):数据库满
├── SQLITE_CANTOPEN (14):无法打开
├── SQLITE_PROTOCOL (15):协议错误
├── SQLITE_SCHEMA (17):Schema变更
├── SQLITE_TOOBIG (18):数据过大
├── SQLITE_CONSTRAINT (19):约束违反
├── SQLITE_MISMATCH (20):类型不匹配
└── SQLITE_MISUSE (21):错误使用

错误处理函数:
├── sqlite3_errmsg():获取错误信息
├── sqlite3_errcode():获取错误码
└── sqlite3_errstr():错误码转字符串

错误处理示例:
int rc = sqlite3_open(“test.db”, &db);
if (rc != SQLITE_OK) {
fprintf(stderr, “Cannot open database: %s\n”,
sqlite3_errmsg(db));
return rc;
}

1.2 sqlite数据库核心API详解

以下是sqlite数据库核心API的详细说明。学习交流加群风哥微信: itpux-com

1.2.1 连接管理API

sqlite数据库连接管理API:

1. sqlite3_open()
├── 功能:打开数据库连接
├── 原型:int sqlite3_open(const char *filename, sqlite3 **ppDb)
├── 参数:filename-数据库文件名,ppDb-连接指针
└── 返回:SQLITE_OK成功,其他失败

2. sqlite3_open_v2()
├── 功能:带标志打开数据库
├── 原型:int sqlite3_open_v2(const char *filename, sqlite3 **ppDb,
│ int flags, const char *zVfs)
├── 标志:SQLITE_OPEN_READONLY/READWRITE/CREATE
└── 返回:SQLITE_OK成功

3. sqlite3_close()
├── 功能:关闭数据库连接
├── 原型:int sqlite3_close(sqlite3 *db)
└── 注意:必须释放所有stmt后关闭

4. sqlite3_close_v2()
├── 功能:安全关闭连接
├── 原型:int sqlite3_close_v2(sqlite3 *db)
└── 特点:自动释放所有资源

5. sqlite3_busy_timeout()
├── 功能:设置忙等待超时
├── 原型:int sqlite3_busy_timeout(sqlite3 *db, int ms)
└── 建议:生产环境设置5000-10000ms

连接管理示例:
#include <sqlite3.h>
#include <stdio.h>

int main() {
sqlite3 *db;
int rc;

// 打开数据库
rc = sqlite3_open(“/sqlite/fgdata/fgedudb.db”, &db);
if (rc != SQLITE_OK) {
fprintf(stderr, “Cannot open database: %s\n”,
sqlite3_errmsg(db));
return 1;
}

// 设置超时
sqlite3_busy_timeout(db, 5000);

// 使用数据库…

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

1.2.2 语句执行API

sqlite数据库语句执行API:

1. sqlite3_prepare_v2()
├── 功能:准备SQL语句
├── 原型:int sqlite3_prepare_v2(sqlite3 *db, const char *zSql,
│ int nByte, sqlite3_stmt **ppStmt, const char **pzTail)
└── 返回:预编译语句对象

2. sqlite3_step()
├── 功能:执行预编译语句
├── 原型:int sqlite3_step(sqlite3_stmt *pStmt)
├── 返回:SQLITE_ROW有数据,SQLITE_DONE完成
└── 循环调用获取所有结果

3. sqlite3_finalize()
├── 功能:销毁预编译语句
├── 原型:int sqlite3_finalize(sqlite3_stmt *pStmt)
└── 必须:释放资源

4. sqlite3_reset()
├── 功能:重置预编译语句
├── 原型:int sqlite3_reset(sqlite3_stmt *pStmt)
└── 用途:重复执行相同语句

5. sqlite3_exec()
├── 功能:执行SQL语句(简化版)
├── 原型:int sqlite3_exec(sqlite3 *db, const char *sql,
│ int (*callback)(void*,int,char**,char**),
│ void *arg, char **errmsg)
└── 适用:简单DDL/DML

语句执行示例:
sqlite3_stmt *stmt;
const char *sql = “SELECT id, username FROM fgedu_users WHERE status = ?”;

// 准备语句
rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK) {
fprintf(stderr, “Failed to prepare: %s\n”, sqlite3_errmsg(db));
return 1;
}

// 绑定参数
sqlite3_bind_int(stmt, 1, 1);

// 执行查询
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
int id = sqlite3_column_int(stmt, 0);
const char *name = (const char*)sqlite3_column_text(stmt, 1);
printf(“id=%d, name=%s\n”, id, name);
}

// 释放语句
sqlite3_finalize(stmt);

1.3 sqlite数据库嵌入式开发基础

sqlite作为嵌入式数据库,在嵌入式系统中应用广泛。更多学习教程公众号风哥教程itpux_com

1.3.1 嵌入式开发特点

sqlite数据库嵌入式开发特点:

1. 资源受限
├── 内存有限
├── 存储有限
├── CPU性能有限
└── 需要优化配置

2. 无服务器架构
├── 数据库嵌入应用
├── 无需独立服务
├── 零配置
└── 易于部署

3. 跨平台支持
├── Linux/Unix
├── Windows
├── macOS
├── 嵌入式Linux
└── RTOS

4. 编译选项
├── 裁剪不需要的功能
├── 减小库大小
├── 优化内存使用
└── 定制构建

嵌入式配置建议:
┌─────────────────┬──────────────────────────┐
│ 配置项 │ 嵌入式建议 │
├─────────────────┼──────────────────────────┤
│ cache_size │ -2000(2MB) │
│ page_size │ 1024-2048 │
│ journal_mode │ DELETE或MEMORY │
│ synchronous │ NORMAL │
│ temp_store │ MEMORY │
└─────────────────┴──────────────────────────┘

嵌入式编译选项:
-DSQLITE_THREADSAFE=0 # 禁用线程安全
-DSQLITE_OMIT_LOAD_EXTENSION # 禁用扩展加载
-DSQLITE_DEFAULT_PAGE_SIZE=1024
-DSQLITE_DEFAULT_CACHE_SIZE=500

Part02-生产环境规划与建议

2.1 sqlite数据库API使用规划

合理的API使用规划可以提高开发效率和程序稳定性。风哥提示:正确使用API是开发高质量应用的基础。

2.1.1 API使用规范

sqlite数据库API使用规范:

1. 连接管理
├── 应用启动时打开连接
├── 使用连接池管理
├── 设置合理的超时
└── 应用退出时关闭连接

2. 语句管理
├── 使用预编译语句
├── 及时释放资源
├── 重用预编译语句
└── 避免SQL注入

3. 事务管理
├── 批量操作使用事务
├── 及时提交或回滚
├── 使用SAVEPOINT
└── 处理并发冲突

4. 错误处理
├── 检查所有返回值
├── 记录错误日志
├── 实现重试机制
└── 优雅降级

5. 资源管理
├── 使用RAII模式
├── 避免资源泄漏
├── 定期检查资源
└── 合理释放资源

代码规范示例:
// 使用RAII封装
class SQLiteDB {
private:
sqlite3 *db;
public:
SQLiteDB(const char *path) {
int rc = sqlite3_open(path, &db);
if (rc != SQLITE_OK) {
throw std::runtime_error(sqlite3_errmsg(db));
}
sqlite3_busy_timeout(db, 5000);
}

~SQLiteDB() {
if (db) sqlite3_close(db);
}

// 禁止拷贝
SQLiteDB(const SQLiteDB&) = delete;
SQLiteDB& operator=(const SQLiteDB&) = delete;
};

2.2 sqlite数据库项目规划建议

合理的项目规划可以确保开发顺利进行。学习交流加群风哥微信: itpux-com

2.2.1 项目结构规划

sqlite数据库项目结构规划:

项目目录结构:
project/
├── src/
│ ├── main.c
│ ├── database.c
│ ├── database.h
│ └── utils.c
├── include/
│ └── sqlite3.h
├── lib/
│ └── libsqlite3.a
├── data/
│ └── fgedudb.db
├── config/
│ └── database.conf
├── Makefile
└── README.md

Makefile示例:
CC = gcc
CFLAGS = -Wall -O2 -I./include
LDFLAGS = -L./lib -lsqlite3 -lpthread -ldl

SRC = src/main.c src/database.c src/utils.c
OBJ = $(SRC:.c=.o)
TARGET = fgedu_app

all: $(TARGET)

$(TARGET): $(OBJ)
$(CC) $(OBJ) -o $@ $(LDFLAGS)

%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@ clean: rm -f $(OBJ) $(TARGET) .PHONY: all clean

2.3 sqlite数据库错误处理规划

完善的错误处理规划可以保证系统稳定性。更多学习教程公众号风哥教程itpux_com

2.3.1 错误处理策略

sqlite数据库错误处理策略:

1. 错误分类处理
├── SQLITE_BUSY:等待重试
├── SQLITE_LOCKED:等待重试
├── SQLITE_CONSTRAINT:检查数据
├── SQLITE_CORRUPT:恢复数据库
└── 其他错误:记录日志

2. 重试机制
├── 设置最大重试次数
├── 指数退避等待
├── 超时放弃
└── 记录重试日志

3. 日志记录
├── 记录错误码
├── 记录错误信息
├── 记录SQL语句
└── 记录时间戳

错误处理封装示例:
int execute_sql(sqlite3 *db, const char *sql) {
char *errmsg = NULL;
int rc;
int retries = 0;
const int max_retries = 3;

while (retries < max_retries) { rc = sqlite3_exec(db, sql, NULL, NULL, &errmsg); if (rc == SQLITE_OK) { return SQLITE_OK; } if (rc == SQLITE_BUSY || rc == SQLITE_LOCKED) { retries++; usleep(100000 * retries); // 指数退避 continue; } // 其他错误 fprintf(stderr, "SQL error: %s\n", errmsg); sqlite3_free(errmsg); return rc; } return SQLITE_BUSY; }

Part03-生产环境项目实施方案

3.1 sqlite数据库连接管理实战

以下是sqlite数据库连接管理的实际操作。学习交流加群风哥QQ113257174

3.1.1 连接管理完整示例

数据库连接管理示例:
/*
* db_manager.c
* from:www.itpux.com.qq113257174.wx:itpux-com
* web: http://www.fgedu.net.cn
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlite3.h>

#define DB_PATH “/sqlite/fgdata/fgedudb.db”
#define BUSY_TIMEOUT 5000

typedef struct {
sqlite3 *db;
int is_open;
} Database;

// 初始化数据库
int db_init(Database *db_ctx) {
int rc;

rc = sqlite3_open(DB_PATH, &db_ctx->db);
if (rc != SQLITE_OK) {
fprintf(stderr, “Cannot open database: %s\n”,
sqlite3_errmsg(db_ctx->db));
return rc;
}

// 配置PRAGMA
char *errmsg = NULL;
rc = sqlite3_exec(db_ctx->db,
“PRAGMA journal_mode = WAL;”
“PRAGMA synchronous = NORMAL;”
“PRAGMA cache_size = -64000;”
“PRAGMA busy_timeout = 5000;”
“PRAGMA foreign_keys = ON;”,
NULL, NULL, &errmsg);

if (rc != SQLITE_OK) {
fprintf(stderr, “PRAGMA error: %s\n”, errmsg);
sqlite3_free(errmsg);
return rc;
}

db_ctx->is_open = 1;
printf(“Database initialized successfully\n”);
return SQLITE_OK;
}

// 关闭数据库
int db_close(Database *db_ctx) {
if (db_ctx->is_open && db_ctx->db) {
sqlite3_close(db_ctx->db);
db_ctx->is_open = 0;
printf(“Database closed\n”);
}
return SQLITE_OK;
}

int main() {
Database db_ctx = {0};

if (db_init(&db_ctx) != SQLITE_OK) {
return 1;
}

// 使用数据库…

db_close(&db_ctx);
return 0;
}

编译执行:
$ gcc -o db_manager db_manager.c -lsqlite3
$ ./db_manager
Database initialized successfully
Database closed

3.2 sqlite数据库查询操作实战

以下是sqlite数据库查询操作的实际操作。风哥提示:预编译语句是查询优化的关键。

3.2.1 查询操作完整示例

查询操作示例:
/*
* query_demo.c
* from:www.itpux.com.qq113257174.wx:itpux-com
* web: http://www.fgedu.net.cn
*/

#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>

// 查询用户列表
int query_users(sqlite3 *db, int status) {
sqlite3_stmt *stmt;
const char *sql = “SELECT id, username, email FROM fgedu_users WHERE status = ?”;
int rc;

// 准备语句
rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK) {
fprintf(stderr, “Failed to prepare: %s\n”, sqlite3_errmsg(db));
return rc;
}

// 绑定参数
sqlite3_bind_int(stmt, 1, status);

printf(“=== User List ===\n”);
printf(“%-5s %-20s %-30s\n”, “ID”, “Username”, “Email”);
printf(“————————————————-\n”);

// 执行查询
int count = 0;
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
int id = sqlite3_column_int(stmt, 0);
const char *username = (const char*)sqlite3_column_text(stmt, 1);
const char *email = (const char*)sqlite3_column_text(stmt, 2);

printf(“%-5d %-20s %-30s\n”, id, username, email);
count++;
}

printf(“————————————————-\n”);
printf(“Total: %d users\n”, count);

// 释放语句
sqlite3_finalize(stmt);
return SQLITE_OK;
}

// 插入用户
int insert_user(sqlite3 *db, const char *username, const char *email) {
sqlite3_stmt *stmt;
const char *sql = “INSERT INTO fgedu_users (username, email) VALUES (?, ?)”;
int rc;

rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK) {
fprintf(stderr, “Failed to prepare: %s\n”, sqlite3_errmsg(db));
return rc;
}

sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 2, email, -1, SQLITE_STATIC);

rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE) {
fprintf(stderr, “Failed to insert: %s\n”, sqlite3_errmsg(db));
sqlite3_finalize(stmt);
return rc;
}

sqlite3_int64 rowid = sqlite3_last_insert_rowid(db);
printf(“Inserted user with ID: %lld\n”, rowid);

sqlite3_finalize(stmt);
return SQLITE_OK;
}

int main() {
sqlite3 *db;
int rc;

rc = sqlite3_open(“/sqlite/fgdata/fgedudb.db”, &db);
if (rc != SQLITE_OK) {
fprintf(stderr, “Cannot open database: %s\n”, sqlite3_errmsg(db));
return 1;
}

// 插入用户
insert_user(db, “fgedu_test”, “test@fgedu.net.cn”);

// 查询用户
query_users(db, 1);

sqlite3_close(db);
return 0;
}

执行结果:
$ ./query_demo
Inserted user with ID: 10005
=== User List ===
ID Username Email
————————————————-
1 fgedu01 fgedu01@fgedu.net.cn
2 fgedu02 fgedu02@fgedu.net.cn

————————————————-
Total: 10005 users

3.3 sqlite数据库事务处理实战

以下是sqlite数据库事务处理的实际操作。更多视频教程www.fgedu.net.cn

3.3.1 事务处理完整示例

事务处理示例:
/*
* transaction_demo.c
* from:www.itpux.com.qq113257174.wx:itpux-com
* web: http://www.fgedu.net.cn
*/

#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>

// 批量插入用户(使用事务)
int batch_insert_users(sqlite3 *db, int count) {
sqlite3_stmt *stmt;
const char *sql = “INSERT INTO fgedu_users (username, email) VALUES (?, ?)”;
int rc, i;
char username[64], email[128];

// 开始事务
rc = sqlite3_exec(db, “BEGIN IMMEDIATE TRANSACTION”, NULL, NULL, NULL);
if (rc != SQLITE_OK) {
fprintf(stderr, “Failed to begin transaction: %s\n”, sqlite3_errmsg(db));
return rc;
}

// 准备语句
rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK) {
fprintf(stderr, “Failed to prepare: %s\n”, sqlite3_errmsg(db));
sqlite3_exec(db, “ROLLBACK”, NULL, NULL, NULL);
return rc;
}

// 批量插入
for (i = 0; i < count; i++) { snprintf(username, sizeof(username), "batch_user_%d", i); snprintf(email, sizeof(email), "batch_%d@fgedu.net.cn", i); sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 2, email, -1, SQLITE_STATIC); rc = sqlite3_step(stmt); if (rc != SQLITE_DONE) { fprintf(stderr, "Failed to insert: %s\n", sqlite3_errmsg(db)); sqlite3_finalize(stmt); sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); return rc; } sqlite3_reset(stmt); } // 提交事务 rc = sqlite3_exec(db, "COMMIT", NULL, NULL, NULL); if (rc != SQLITE_OK) { fprintf(stderr, "Failed to commit: %s\n", sqlite3_errmsg(db)); sqlite3_finalize(stmt); return rc; } sqlite3_finalize(stmt); printf("Batch inserted %d users successfully\n", count); return SQLITE_OK; } // 使用SAVEPOINT int transfer_balance(sqlite3 *db, int from_id, int to_id, double amount) { char sql[256]; int rc; // 开始事务 rc = sqlite3_exec(db, "BEGIN IMMEDIATE TRANSACTION", NULL, NULL, NULL); if (rc != SQLITE_OK) return rc; // 设置保存点 rc = sqlite3_exec(db, "SAVEPOINT transfer_sp", NULL, NULL, NULL); if (rc != SQLITE_OK) { sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); return rc; } // 扣款 snprintf(sql, sizeof(sql), "UPDATE fgedu_accounts SET balance = balance - %f WHERE id = %d", amount, from_id); rc = sqlite3_exec(db, sql, NULL, NULL, NULL); if (rc != SQLITE_OK) { sqlite3_exec(db, "ROLLBACK TO SAVEPOINT transfer_sp", NULL, NULL, NULL); sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); return rc; } // 入账 snprintf(sql, sizeof(sql), "UPDATE fgedu_accounts SET balance = balance + %f WHERE id = %d", amount, to_id); rc = sqlite3_exec(db, sql, NULL, NULL, NULL); if (rc != SQLITE_OK) { sqlite3_exec(db, "ROLLBACK TO SAVEPOINT transfer_sp", NULL, NULL, NULL); sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); return rc; } // 释放保存点 sqlite3_exec(db, "RELEASE SAVEPOINT transfer_sp", NULL, NULL, NULL); // 提交事务 rc = sqlite3_exec(db, "COMMIT", NULL, NULL, NULL); if (rc != SQLITE_OK) return rc; printf("Transfer %.2f from %d to %d successfully\n", amount, from_id, to_id); return SQLITE_OK; } int main() { sqlite3 *db; sqlite3_open("/sqlite/fgdata/fgedudb.db", &db); // 批量插入 batch_insert_users(db, 100); // 转账 transfer_balance(db, 1, 2, 100.00); sqlite3_close(db); return 0; }

Part04-生产案例与实战讲解

4.1 sqlite数据库CRUD操作案例

以下是sqlite数据库CRUD操作的完整案例。学习交流加群风哥微信: itpux-com

4.1.1 完整CRUD封装

CRUD操作封装示例:
/*
* crud_api.c
* from:www.itpux.com.qq113257174.wx:itpux-com
* web: http://www.fgedu.net.cn
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlite3.h>

// 用户结构体
typedef struct {
int id;
char username[64];
char email[128];
int status;
} User;

// 创建用户
int user_create(sqlite3 *db, const User *user) {
sqlite3_stmt *stmt;
const char *sql = “INSERT INTO fgedu_users (username, email, status) VALUES (?, ?, ?)”;
int rc;

rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK) return rc;

sqlite3_bind_text(stmt, 1, user->username, -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 2, user->email, -1, SQLITE_STATIC);
sqlite3_bind_int(stmt, 3, user->status);

rc = sqlite3_step(stmt);
sqlite3_finalize(stmt);

return (rc == SQLITE_DONE) ? SQLITE_OK : rc;
}

// 读取用户
int user_read(sqlite3 *db, int id, User *user) {
sqlite3_stmt *stmt;
const char *sql = “SELECT id, username, email, status FROM fgedu_users WHERE id = ?”;
int rc;

rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK) return rc;

sqlite3_bind_int(stmt, 1, id);

rc = sqlite3_step(stmt);
if (rc == SQLITE_ROW) {
user->id = sqlite3_column_int(stmt, 0);
strncpy(user->username, (const char*)sqlite3_column_text(stmt, 1), 63);
strncpy(user->email, (const char*)sqlite3_column_text(stmt, 2), 127);
user->status = sqlite3_column_int(stmt, 3);
rc = SQLITE_OK;
} else {
rc = SQLITE_NOTFOUND;
}

sqlite3_finalize(stmt);
return rc;
}

// 更新用户
int user_update(sqlite3 *db, const User *user) {
sqlite3_stmt *stmt;
const char *sql = “UPDATE fgedu_users SET username = ?, email = ?, status = ? WHERE id = ?”;
int rc;

rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK) return rc;

sqlite3_bind_text(stmt, 1, user->username, -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 2, user->email, -1, SQLITE_STATIC);
sqlite3_bind_int(stmt, 3, user->status);
sqlite3_bind_int(stmt, 4, user->id);

rc = sqlite3_step(stmt);
sqlite3_finalize(stmt);

return (rc == SQLITE_DONE) ? SQLITE_OK : rc;
}

// 删除用户
int user_delete(sqlite3 *db, int id) {
sqlite3_stmt *stmt;
const char *sql = “DELETE FROM fgedu_users WHERE id = ?”;
int rc;

rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK) return rc;

sqlite3_bind_int(stmt, 1, id);

rc = sqlite3_step(stmt);
sqlite3_finalize(stmt);

return (rc == SQLITE_DONE) ? SQLITE_OK : rc;
}

int main() {
sqlite3 *db;
User user;

sqlite3_open(“/sqlite/fgdata/fgedudb.db”, &db);

// Create
User new_user = {0, “fgedu_new”, “new@fgedu.net.cn”, 1};
user_create(db, &new_user);
printf(“User created\n”);

// Read
user_read(db, 1, &user);
printf(“User: id=%d, name=%s\n”, user.id, user.username);

// Update
strcpy(user.email, “updated@fgedu.net.cn”);
user_update(db, &user);
printf(“User updated\n”);

// Delete
user_delete(db, 100);
printf(“User deleted\n”);

sqlite3_close(db);
return 0;
}

4.2 sqlite数据库批量操作案例

以下是sqlite数据库批量操作的案例。风哥提示:批量操作使用事务可以显著提升性能。

4.2.1 批量导入导出案例

批量操作案例:
/*
* batch_ops.c
* from:www.itpux.com.qq113257174.wx:itpux-com
* web: http://www.fgedu.net.cn
*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sqlite3.h>

#define BATCH_SIZE 1000

// 批量插入性能测试
void benchmark_insert(sqlite3 *db, int total) {
sqlite3_stmt *stmt;
clock_t start, end;
int i, batches;

const char *sql = “INSERT INTO fgedu_test (name, value) VALUES (?, ?)”;

// 不使用事务
printf(“Without transaction:\n”);
start = clock();
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
for (i = 0; i < total; i++) { sqlite3_bind_text(stmt, 1, "test", -1, SQLITE_STATIC); sqlite3_bind_int(stmt, 2, i); sqlite3_step(stmt); sqlite3_reset(stmt); } sqlite3_finalize(stmt); end = clock(); printf(" Time: %.2f seconds\n", (double)(end - start) / CLOCKS_PER_SEC); // 清空表 sqlite3_exec(db, "DELETE FROM fgedu_test", NULL, NULL, NULL); // 使用事务 printf("With transaction:\n"); start = clock(); batches = (total + BATCH_SIZE - 1) / BATCH_SIZE; for (int batch = 0; batch < batches; batch++) { sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, NULL); sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); int start_idx = batch * BATCH_SIZE; int end_idx = (start_idx + BATCH_SIZE < total) ? start_idx + BATCH_SIZE : total; for (i = start_idx; i < end_idx; i++) { sqlite3_bind_text(stmt, 1, "test", -1, SQLITE_STATIC); sqlite3_bind_int(stmt, 2, i); sqlite3_step(stmt); sqlite3_reset(stmt); } sqlite3_finalize(stmt); sqlite3_exec(db, "COMMIT", NULL, NULL, NULL); } end = clock(); printf(" Time: %.2f seconds\n", (double)(end - start) / CLOCKS_PER_SEC); } int main() { sqlite3 *db; sqlite3_open("/sqlite/fgdata/fgedudb.db", &db); // 创建测试表 sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS fgedu_test (" "id INTEGER PRIMARY KEY, name TEXT, value INTEGER)", NULL, NULL, NULL); // 性能测试 benchmark_insert(db, 10000); sqlite3_close(db); return 0; } 执行结果: $ ./batch_ops Without transaction: Time: 5.23 seconds With transaction: Time: 0.15 seconds

4.3 sqlite数据库嵌入式应用案例

以下是sqlite数据库嵌入式应用的案例。更多学习教程公众号风哥教程itpux_com

4.3.1 嵌入式数据采集案例

嵌入式数据采集示例:
/*
* data_collector.c
* from:www.itpux.com.qq113257174.wx:itpux-com
* web: http://www.fgedu.net.cn
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sqlite3.h>

#define DB_PATH “/sqlite/fgdata/sensor.db”
#define MAX_CACHE 100

// 传感器数据结构
typedef struct {
time_t timestamp;
char sensor_id[32];
double value;
} SensorData;

// 数据缓存
typedef struct {
SensorData data[MAX_CACHE];
int count;
sqlite3 *db;
sqlite3_stmt *stmt;
} DataCache;

// 初始化缓存
int cache_init(DataCache *cache) {
int rc;

rc = sqlite3_open(DB_PATH, &cache->db);
if (rc != SQLITE_OK) return rc;

// 创建表
rc = sqlite3_exec(cache->db,
“CREATE TABLE IF NOT EXISTS fgedu_sensor_data (”
“id INTEGER PRIMARY KEY AUTOINCREMENT, ”
“timestamp INTEGER, ”
“sensor_id TEXT, ”
“value REAL)”,
NULL, NULL, NULL);
if (rc != SQLITE_OK) return rc;

// 配置PRAGMA
sqlite3_exec(cache->db, “PRAGMA journal_mode = WAL”, NULL, NULL, NULL);
sqlite3_exec(cache->db, “PRAGMA synchronous = NORMAL”, NULL, NULL, NULL);

// 准备插入语句
rc = sqlite3_prepare_v2(cache->db,
“INSERT INTO fgedu_sensor_data (timestamp, sensor_id, value) VALUES (?, ?, ?)”,
-1, &cache->stmt, NULL);
if (rc != SQLITE_OK) return rc;

cache->count = 0;
return SQLITE_OK;
}

// 添加数据到缓存
void cache_add(DataCache *cache, const char *sensor_id, double value) {
if (cache->count >= MAX_CACHE) {
// 缓存满,写入数据库
cache_flush(cache);
}

cache->data[cache->count].timestamp = time(NULL);
strncpy(cache->data[cache->count].sensor_id, sensor_id, 31);
cache->data[cache->count].value = value;
cache->count++;
}

// 刷新缓存到数据库
int cache_flush(DataCache *cache) {
int i, rc;

if (cache->count == 0) return SQLITE_OK;

rc = sqlite3_exec(cache->db, “BEGIN TRANSACTION”, NULL, NULL, NULL);
if (rc != SQLITE_OK) return rc;

for (i = 0; i < cache->count; i++) {
sqlite3_bind_int64(cache->stmt, 1, cache->data[i].timestamp);
sqlite3_bind_text(cache->stmt, 2, cache->data[i].sensor_id, -1, SQLITE_STATIC);
sqlite3_bind_double(cache->stmt, 3, cache->data[i].value);

rc = sqlite3_step(cache->stmt);
sqlite3_reset(cache->stmt);

if (rc != SQLITE_DONE) {
sqlite3_exec(cache->db, “ROLLBACK”, NULL, NULL, NULL);
return rc;
}
}

rc = sqlite3_exec(cache->db, “COMMIT”, NULL, NULL, NULL);
if (rc == SQLITE_OK) {
printf(“Flushed %d records to database\n”, cache->count);
cache->count = 0;
}

return rc;
}

// 关闭缓存
void cache_close(DataCache *cache) {
cache_flush(cache);
sqlite3_finalize(cache->stmt);
sqlite3_close(cache->db);
}

int main() {
DataCache cache;
int i;

if (cache_init(&cache) != SQLITE_OK) {
fprintf(stderr, “Failed to initialize cache\n”);
return 1;
}

printf(“Collecting sensor data…\n”);

// 模拟数据采集
for (i = 0; i < 250; i++) { char sensor_id[32]; snprintf(sensor_id, sizeof(sensor_id), "TEMP_%02d", i % 10); double value = 20.0 + (rand() % 100) / 10.0; cache_add(&cache, sensor_id, value); } cache_close(&cache); printf("Data collection completed\n"); return 0; }

Part05-风哥经验总结与分享

5.1 sqlite数据库API最佳实践

基于多年的实践经验,以下是sqlite数据库API的最佳实践总结。学习交流加群风哥QQ113257174

5.1.1 API最佳实践总结

sqlite数据库API最佳实践:

1. 连接管理
├── 使用连接池
├── 设置合理超时
├── 配置PRAGMA
└── 及时关闭连接

2. 语句管理
├── 使用预编译语句
├── 重用预编译语句
├── 及时释放资源
└── 使用参数绑定

3. 事务管理
├── 批量操作使用事务
├── 使用IMMEDIATE事务
├── 及时提交或回滚
└── 使用SAVEPOINT

4. 错误处理
├── 检查所有返回值
├── 实现重试机制
├── 记录错误日志
└── 优雅降级

5. 性能优化
├── 使用事务批量操作
├── 使用预编译语句
├── 合理配置缓存
└── 避免频繁开关连接

5.2 sqlite数据库开发技巧

以下是sqlite数据库开发的技巧总结。from sqlite视频:www.itpux.com

5.2.1 开发技巧汇总

sqlite数据库开发技巧:

1. 代码组织
├── 封装数据库操作
├── 使用RAII管理资源
├── 统一错误处理
└── 模块化设计

2. 性能优化
├── 批量操作用事务
├── 预编译语句重用
├── 合理使用索引
└── 避免全表扫描

3. 内存管理
├── 及时释放资源
├── 避免内存泄漏
├── 使用缓存
└── 监控内存使用

4. 调试技巧
├── 启用日志
├── 使用sqlite3_errmsg
├── 分析执行计划
└── 单元测试

5. 安全考虑
├── 参数化查询
├── 输入验证
├── 数据加密
└── 权限控制

5.3 sqlite数据库嵌入式开发总结

综合各种因素,以下是sqlite数据库嵌入式开发的总结。更多视频教程www.fgedu.net.cn

5.3.1 嵌入式开发总结

sqlite数据库嵌入式开发总结:

核心要点:
├── 理解API设计理念
├── 正确管理资源
├── 合理使用事务
├── 完善错误处理
└── 持续性能优化

开发流程:
├── 1. 设计数据库结构
├── 2. 封装数据库操作
├── 3. 实现业务逻辑
├── 4. 测试验证
├── 5. 性能优化
└── 6. 部署上线

最佳实践:
├── 使用预编译语句
├── 批量操作用事务
├── 合理配置PRAGMA
├── 完善错误处理
└── 定期维护数据库

注意事项:
├── 资源必须释放
├── 检查所有返回值
├── 避免SQL注入
├── 控制事务大小
└── 监控性能指标

风哥总结:sqlite的C/C++ API设计简洁高效,是嵌入式数据库开发的核心接口。正确使用API,合理管理资源,完善错误处理,可以开发出高质量的应用程序。生产环境建议封装数据库操作,使用预编译语句,批量操作使用事务,并建立完善的监控和日志体系。

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息