了解应用程序如何在内部与 SQLite 交互

发布: (2026年1月4日 GMT+8 20:49)
7 min read
原文: Dev.to

I’m happy to help translate the article, but I need the text you’d like translated. Could you please paste the content (or the portion you want translated) here? I’ll keep the source link unchanged and preserve all formatting, markdown, and technical terms as requested.

Source:

SQLite 概述

SQLite 的一个决定性优势在于应用程序与其交互的方式既简洁又可预测。

不同于客户端‑服务器数据库,SQLite 直接运行在应用程序进程内部,提供了一个小而强大的 C API,让开发者能够精确控制查询执行、内存使用和性能。

核心数据结构

  • sqlite3 → 表示 数据库连接
  • sqlite3_stmt → 表示 已准备好的 SQL 语句

应用程序对 SQLite 的所有操作都围绕这两个对象展开。

SQLite architecture diagram

从 SQL 文本到可执行字节码

当应用程序向 SQLite 发送 SQL 时,引擎 不会直接执行原始文本。
相反,SQLite 采用编译‑执行模型,类似于现代编程语言。

Compilation pipeline

sqlite3_prepare — 将 SQL 编译为字节码

sqlite3_prepare(db, sql, -1, &stmt, NULL);

内部发生的过程至关重要:

  1. 解析 SQL。
  2. 验证 模式对象(表、索引、列)。
  3. 翻译 SQL 为 内部字节码程序
  4. 包装 该程序到 sqlite3_stmt 对象中(预编译语句)。

在 SQLite 术语中:

  • 预编译语句 就是 字节码程序。
  • 字节码程序 是 SQLite 虚拟机执行的抽象指令序列。

如果准备成功,sqlite3_prepare 返回 SQLITE_OK;否则返回详细的错误码(语法错误、缺少表等)。
此时 尚未执行任何操作——语句已编译但处于休眠状态,就像已加载等待运行的程序。

执行预处理语句逐行

sqlite3_step — 驱动 SQLite 虚拟机

sqlite3_step(stmt);

每次调用 sqlite3_step 都会运行字节码程序,直到出现以下两种情况之一

  • 产生一行新的结果,或
  • 程序执行完毕。

返回值告诉应用程序到底发生了什么:

返回码含义
SQLITE_ROW行已准备好读取
SQLITE_DONE执行已完成

SELECT 语句

  • 游标最初位于 第一行之前
  • 每次调用 sqlite3_step 都会将游标 向前 移动。
  • 行会 一次产生一行(不会向后移动)。

INSERT / UPDATE / DELETE / CREATE / DROP

  • 不产生行。
  • sqlite3_step 会立即返回 SQLITE_DONE

这种逐行执行模型是 SQLite 极其节省内存的关键原因。

读取列数据的安全方法

sqlite3_column_* — 从行中提取值

sqlite3_step 返回 SQLITE_ROW 时,可以使用特定类型的 API 读取列值:

  • sqlite3_column_int
  • sqlite3_column_int64
  • sqlite3_column_double
  • sqlite3_column_text
  • sqlite3_column_blob

每个函数都保证返回的值已转换为请求的 C 类型。

对于文本和 BLOB 数据,大小至关重要。SQLite 提供:

int bytes = sqlite3_column_bytes(stmt, col_index);

这会告诉应用程序列实际占用的字节数,对安全的内存处理至关重要。

错误处理在执行期间

在逐步执行语句时,SQLite 可能会遇到运行时问题。在这种情况下,sqlite3_step 可以返回:

返回码含义
SQLITE_BUSY数据库被锁定;应用程序可以稍后重试。
SQLITE_ERROR发生运行时错误(例如约束冲突)。必须停止执行。
SQLITE_MISUSEAPI 使用不当(例如在已完成的语句上调用 sqlite3_step)。

这些明确的返回码让 SQLite 清晰地说明了出错原因以及应用程序接下来应采取的措施。

清理:结束语句生命周期

sqlite3_finalize — 销毁预处理语句

sqlite3_finalize(stmt);

完成后会执行以下操作:

  • 删除字节码程序。
  • 释放与该语句关联的所有内存。
  • 永久使 sqlite3_stmt 句柄失效。

如果语句仍在执行,SQLite 将把完成视为一次中断:

  • 未完成的更改将被回滚。
  • 执行被中止,返回 SQLITE_ABORT

未能完成语句的终结是 SQLite 应用程序中最常见的资源泄漏原因之一。

SQLite 应用中的源泄漏

关闭数据库连接

sqlite3_close — 释放数据库句柄

sqlite3_close(db);

这将释放与该连接关联的所有资源。

重要规则:

如果 仍有任何已准备好的语句处于活动状态sqlite3_close 会返回 SQLITE_BUSY
连接会保持打开,直到所有语句都被 finalize。

此严格规则确保数据库完整性并防止悬挂的执行上下文。

综合运用:SQLite 执行模式

在实际使用中,SQLite 的使用遵循一个非常一致的生命周期:

  1. 打开数据库连接(sqlite3_open
  2. 预编译 SQL 语句(sqlite3_prepare
  3. 如有需要,绑定数值
  4. 使用 sqlite3_step 执行(可能需要多次)
  5. 使用 sqlite3_column_* 读取列值
  6. 如需复用语句,重置语句
  7. 结束语句(sqlite3_finalize
  8. 关闭数据库连接(sqlite3_close

这套小而有纪律的 API 表面是 SQLite 在全球操作系统、浏览器、移动应用和嵌入式系统中受到信赖的主要原因。

我关于 SQLite 的实验和实际操作将会放在这里:
lovestaco/sqlite

参考文献

欢迎任何反馈或贡献!

它是在线的、开源的,随时可供任何人使用。

⭐ 在 GitHub 上给它加星: FreeDevTools

Back to Blog

相关文章

阅读更多 »

SQLite 中的系统事务到用户事务

用户事务:逃离自动提交 默认情况下,SQLite 运行在 autocommit 模式。每个非 SELECT 语句都会被包装在它自己的事务中:!Autocommit tr...