下面是一份 SQLite C 接口(C API)完整实战手册,专为 美国开发者(时区 PST/PDT)定制,涵盖:
- 核心 API 详解
- 防注入参数化查询
- 事务、错误处理、回调函数
- US 本地时间处理(PST/PDT 自动切换)
- 性能优化(WAL、缓存)
- 生产级封装模板(C)
一、SQLite C API 核心函数(10 个必会)
| 函数 | 作用 | 返回值 |
|---|---|---|
sqlite3_open() | 打开数据库 | SQLITE_OK |
sqlite3_prepare_v2() | 编译 SQL | sqlite3_stmt* |
sqlite3_step() | 执行一步 | SQLITE_ROW / SQLITE_DONE |
sqlite3_column_*() | 读取列值 | 对应类型 |
sqlite3_bind_*() | 绑定参数 | SQLITE_OK |
sqlite3_finalize() | 释放语句 | SQLITE_OK |
sqlite3_close() | 关闭数据库 | SQLITE_OK |
sqlite3_exec() | 快速执行 + 回调 | SQLITE_OK |
sqlite3_errmsg() | 错误信息 | const char* |
sqlite3_changes() | 影响行数 | int |
二、完整 C 示例:用户管理系统
#include <sqlite3.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
// US 本地时间(自动识别 PST/PDT)
char* now_us() {
time_t t = time(NULL);
struct tm *tm = localtime(&t);
static char buf[64];
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm);
return buf;
}
// 回调:打印查询结果
int callback(void *data, int argc, char **argv, char **colName) {
for (int i = 0; i < argc; i++) {
printf("%s: %s ", colName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
int main() {
sqlite3 *db;
sqlite3_stmt *stmt;
char *errMsg = NULL;
int rc;
// 1. 打开数据库
rc = sqlite3_open("app.db", &db);
if (rc != SQLITE_OK) {
fprintf(stderr, "打开数据库失败: %s\n", sqlite3_errmsg(db));
return 1;
}
// 2. 启用 WAL + 优化
sqlite3_exec(db, "PRAGMA journal_mode = WAL;", NULL, NULL, NULL);
sqlite3_exec(db, "PRAGMA synchronous = NORMAL;", NULL, NULL, NULL);
sqlite3_exec(db, "PRAGMA cache_size = -20000;", NULL, NULL, NULL); // 20MB
// 3. 创建表
const char *create_sql =
"CREATE TABLE IF NOT EXISTS users ("
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
" name TEXT NOT NULL,"
" email TEXT UNIQUE,"
" created_at TEXT DEFAULT (datetime('now', 'localtime'))"
");"
"CREATE INDEX IF NOT EXISTS idx_email ON users(email);";
sqlite3_exec(db, create_sql, NULL, NULL, &errMsg);
// 4. 参数化插入(防注入)
const char *insert_sql = "INSERT INTO users (name, email) VALUES (?, ?);";
rc = sqlite3_prepare_v2(db, insert_sql, -1, &stmt, NULL);
if (rc != SQLITE_OK) {
fprintf(stderr, "准备语句失败: %s\n", sqlite3_errmsg(db));
goto cleanup;
}
const char *name = "John Doe";
const char *email = "john@example.com";
sqlite3_bind_text(stmt, 1, name, -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, email, -1, SQLITE_TRANSIENT);
if (sqlite3_step(stmt) != SQLITE_DONE) {
fprintf(stderr, "插入失败: %s\n", sqlite3_errmsg(db));
} else {
printf("插入成功,ID: %lld\n", sqlite3_last_insert_rowid(db));
}
sqlite3_finalize(stmt);
// 5. 查询所有用户
printf("\n--- 用户列表 ---\n");
sqlite3_exec(db, "SELECT * FROM users;", callback, NULL, &errMsg);
// 6. 事务批量插入
sqlite3_exec(db, "BEGIN IMMEDIATE;", NULL, NULL, NULL);
for (int i = 1; i <= 3; i++) {
char n[32], e[64];
snprintf(n, sizeof(n), "User%d", i);
snprintf(e, sizeof(e), "user%d@test.com", i);
sqlite3_prepare_v2(db, insert_sql, -1, &stmt, NULL);
sqlite3_bind_text(stmt, 1, n, -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, e, -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
}
sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL);
printf("批量插入完成!\n");
cleanup:
sqlite3_close(db);
return 0;
}
三、US 时间处理(自动 PST/PDT)
SQLite 不自动识别夏令时,但 localtime 使用系统时区:
// 插入当前 US 时间(自动 PST/PDT)
INSERT INTO logs (action, created_at)
VALUES ('login', datetime('now', 'localtime'));
C 中获取本地时间:
char* now_us() {
time_t t = time(NULL);
struct tm *tm = localtime(&t); // 自动处理 PST/PDT
static char buf[64];
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm); // 带时区名
return buf; // 如: 2025-11-06 17:36:00 PST
}
四、防注入:参数化查询(必须)
// 危险:字符串拼接
char sql[256];
snprintf(sql, sizeof(sql), "SELECT * FROM users WHERE email = '%s';", input);
// 安全:参数化
const char *safe_sql = "SELECT * FROM users WHERE email = ?;";
sqlite3_prepare_v2(db, safe_sql, -1, &stmt, NULL);
sqlite3_bind_text(stmt, 1, input, -1, SQLITE_TRANSIENT);
五、生产级封装(推荐)
typedef struct {
sqlite3 *db;
} DB;
int db_open(DB *db, const char *path) {
return sqlite3_open(path, &db->db);
}
void db_close(DB *db) {
if (db->db) sqlite3_close(db->db);
}
int db_exec(DB *db, const char *sql) {
char *err;
int rc = sqlite3_exec(db->db, sql, NULL, NULL, &err);
if (rc != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", err);
sqlite3_free(err);
}
return rc;
}
六、性能优化(US 高并发场景)
// 开启 WAL(推荐生产)
sqlite3_exec(db, "PRAGMA journal_mode = WAL;", NULL, NULL, NULL);
// 增大缓存
sqlite3_exec(db, "PRAGMA cache_size = -64000;", NULL, NULL, NULL); // 64MB
// 页面大小
sqlite3_exec(db, "PRAGMA page_size = 4096;", NULL, NULL, NULL);
七、编译命令
# Linux/macOS
gcc main.c -lsqlite3 -o app
# Windows (MinGW)
gcc main.c -lsqlite3 -o app.exe
# 静态链接(嵌入式)
gcc sqlite3.c your_app.c -pthread -ldl -lm -o app
八、常见错误处理
| 错误 | 检查点 |
|---|---|
SQLITE_BUSY | 数据库被锁 → 用 WAL 或重试 |
SQLITE_CONSTRAINT | 唯一约束冲突 |
SQLITE_ERROR | SQL 语法错误 |
| 内存泄漏 | 每个 prepare 必须 finalize |
if (rc != SQLITE_OK) {
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
goto cleanup;
}
九、快速模板(复制即用)
1. 安全查询单条
const char *get_email(sqlite3 *db, int id) {
const char *sql = "SELECT email FROM users WHERE id = ?;";
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) return NULL;
sqlite3_bind_int(stmt, 1, id);
if (sqlite3_step(stmt) == SQLITE_ROW) {
const char *email = (const char*)sqlite3_column_text(stmt, 0);
char *result = strdup(email);
sqlite3_finalize(stmt);
return result;
}
sqlite3_finalize(stmt);
return NULL;
}
2. 带回调查询
sqlite3_exec(db, "SELECT * FROM users WHERE created_at > '2025-11-01';", callback, NULL, NULL);
十、总结:C API 最佳实践
| 项目 | 推荐 |
|---|---|
| 防注入 | 必须用 ? + sqlite3_bind_* |
| 时间 | 用 datetime('now','localtime') |
| 事务 | 批量操作用 BEGIN ... COMMIT |
| 并发 | 开启 WAL |
| 资源 | finalize + close |
| 错误 | 每次检查 rc |
需要我为你生成:
- REST API 后端(C + SQLite)?
- 高性能日志系统(100K QPS)?
- iOS/Android NDK 封装?
把需求发我,10 分钟出完整代码!