一、总结
以下两个对象和八个方法构成了 SQLite 接口的基本元素:
sqlite3 → 数据库连接对象。由 sqlite3_open()创建并由 sqlite3_close( )销毁。
sqlite3_stmt → 准备好的语句对象。由 sqlite3_prepare()创建并由 sqlite3_finalize( )销毁。
sqlite3_open() → 打开与新的或现有 SQLite 数据库的连接。sqlite3的构造函数。
sqlite3_prepare() → 将 SQL 文本编译成字节码,以执行查询或更新数据库的工作。sqlite3_stmt的构造函数。
sqlite3_bind() → 将应用程序数据存储到 原始 SQL 的 参数中。
sqlite3_step() → 将sqlite3_stmt推进到下一个结果行或完成。
sqlite3_column() → sqlite3_stmt当前结果行中的列值。
sqlite3_finalize() → sqlite3_stmt的析构函数。
sqlite3_close() → sqlite3的析构函数。
sqlite3_exec() → 一个包装函数,它为一个或多个 SQL 语句的字符串 执行sqlite3_prepare()、 sqlite3_step()、 sqlite3_column()和sqlite3_finalize() 。
2.简介
SQLite 有超过 225 个 API。但是,大多数 API 都是可选的并且非常专业,初学者可以忽略。核心 API 小巧、简单且易于学习。本文总结了核心 API。
一个单独的文档,SQLite C/C++ Interface,为 SQLite 的所有 C/C++ API 提供了详细的规范。一旦读者理解了 SQLite 的基本操作原理, 该文档就应该用作参考指南。本文仅作为介绍,既不是 SQLite API 的完整参考也不是权威参考。
3.核心对象和接口
SQL数据库引擎的主要任务是评估SQL的SQL语句。为此,开发人员需要两个对象:
严格来说,prepared statement对象不是必需的,因为可以使用便利的包装器接口sqlite3_exec或 sqlite3_get_table,这些便利的包装器封装和隐藏了prepared statement对象。然而,要充分利用 SQLite,需要 了解 准备好的语句。
数据库连接和准备好的语句对象由 下面列出的一小组 C/C++ 接口例程控制。
请注意,上面的例程列表是概念性的,而不是实际的。其中许多例程有多个版本。例如,上面的列表显示了一个名为sqlite3_open()的例程,而实际上有三个单独的例程以略有不同的方式完成同一件事: sqlite3_open()、sqlite3_open16()和sqlite3_open_v2()。该列表提到了 sqlite3_column() ,而实际上不存在这样的例程。列表中显示的“sqlite3_column()”是整个例程系列的占位符,这些例程以各种数据类型添加列数据。
以下是核心接口功能的摘要:
此例程打开一个到 SQLite 数据库文件的连接并返回一个 数据库连接对象。这通常是应用程序进行的第一个 SQLite API 调用,并且是大多数其他 SQLite API 的先决条件。许多 SQLite 接口需要一个指向数据库连接对象的指针作为它们的第一个参数,并且可以被认为是数据库连接对象上的方法。该例程是数据库连接对象的构造函数。
此例程将 SQL 文本转换为准备好的语句对象并返回指向该对象的指针。该接口需要一个由先前调用sqlite3_open()创建的数据库连接指针和一个包含要准备的 SQL 语句的文本字符串。该 API 实际上并不评估 SQL 语句。它只是准备用于评估的 SQL 语句。
将每个 SQL 语句视为一个小型计算机程序。sqlite3_prepare()的目的是将该程序编译成目标代码。准备好的语句是目标代码。sqlite3_step()接口然后运行目标代码以获得结果。
新应用程序应始终调用sqlite3_prepare_v2()而不是sqlite3_prepare()。保留旧的sqlite3_prepare()是为了向后兼容。但是sqlite3_prepare_v2()提供了一个更好的接口。
此例程用于评估先前由sqlite3_prepare()接口创建的准备好的语句。对语句进行评估,直到第一行结果可用为止。要前进到第二行结果,请再次调用sqlite3_step()。继续调用sqlite3_step()直到语句完成。不返回结果的语句(例如:INSERT、UPDATE 或 DELETE 语句)在一次调用sqlite3_step()时运行完成。
此例程从结果集的当前行返回单个列,用于由sqlite3_step()评估的准备好的语句。每次sqlite3_step()以新的结果集行停止时,可以多次调用此例程以查找该行中所有列的值。
如上所述,在 SQLite API 中确实没有“sqlite3_column()”函数这样的东西。相反,我们在这里所说的“sqlite3_column()”是整个函数系列的占位符,这些函数从各种数据类型的结果集中返回一个值。该系列中还有一些例程返回结果的大小(如果它是字符串或 BLOB)和结果集中的列数。
此例程会破坏由先前调用sqlite3_prepare()创建的准备好的语句。为了避免内存泄漏,必须使用对此例程的调用来销毁每个准备好的语句。
此例程关闭先前通过调用sqlite3_open()打开的数据库连接。所有与连接关联的准备好的语句都应该在关闭连接之前 完成。
4.核心例程和对象的典型用法
应用程序通常会 在初始化期间使用sqlite3_open()创建单个数据库连接。请注意,sqlite3_open()可用于打开现有的数据库文件或创建和打开新的数据库文件。虽然许多应用程序只使用一个数据库连接,但应用程序没有理由不能多次调用sqlite3_open()以打开多个数据库连接- 无论是到同一个数据库还是到不同的数据库。有时,多线程应用程序会为每个线程创建单独的数据库连接。注意单个数据库连接可以使用ATTACH SQL 命令访问两个或多个数据库,因此不必为每个数据库文件建立单独的数据库连接。
许多应用程序在关闭时调用 sqlite3_close()来 破坏它们的数据库连接。或者,例如,使用 SQLite 作为其应用程序文件格式的应用程序可能会打开数据库连接以响应文件/打开菜单操作,然后销毁相应的数据库连接以响应文件/关闭菜单。
要运行 SQL 语句,应用程序遵循以下步骤:
- 使用sqlite3_prepare()创建准备好的语句。
- 通过调用sqlite3_step()一次或多次来评估准备好的语句。
- 对于查询,通过在两次调用sqlite3_step ()之间调用 sqlite3_column() 来提取结果 。
- 使用sqlite3_finalize()销毁准备好的语句。
上述内容是有效使用 SQLite 真正需要了解的全部内容。剩下的就是优化和细节。
5.围绕核心例程的便利包装
sqlite3_exec()接口是一个方便 的包装器,它通过单个函数调用执行上述所有四个步骤。传递给sqlite3_exec()的回调函数用于处理结果集的每一行。sqlite3_get_table()是另一个方便的包装器,它完成上述所有四个步骤。sqlite3_get_table()接口与sqlite3_exec()的不同之处在于它将查询结果存储在堆内存中而不是调用回调。
重要的是要认识到sqlite3_exec()和 sqlite3_get_table()都不能做任何使用核心例程无法完成的事情。事实上,这些包装器纯粹是根据核心例程来实现的。
6.绑定参数和重用准备好的语句
在前面的讨论中,假定每个 SQL 语句都准备一次、计算一次,然后销毁。但是,SQLite 允许多次评估同一个 准备好的语句。这是使用以下例程完成的:
在通过一次或多次调用 sqlite3_step()评估准备好的语句后,可以重置它以便通过调用sqlite3_reset()再次评估。将sqlite3_reset()视为将准备好的语句程序倒回到开头。在现有准备好的语句上使用sqlite3_reset()而不是创建新的准备好的语句可以避免不必要地调用 sqlite3_prepare()。对于许多 SQL 语句,运行sqlite3_prepare()所需的时间等于或超过 sqlite3_step()所需的时间. 因此,避免调用sqlite3_prepare()可以显着提高性能。
多次评估完全相同的SQL 语句 通常没有用。更常见的是,人们想要评估类似的陈述。例如,您可能想要使用不同的值多次评估 INSERT 语句。或者您可能希望在 WHERE 子句中使用不同的键多次评估同一个查询。为了适应这一点,SQLite 允许 SQL 语句包含 在评估之前“绑定”到值的参数。稍后可以更改这些值,并且可以使用新值第二次评估 相同的准备语句。
SQLite 允许在任何允许字符串文字、数字常量或 NULL 的地方使用参数。(参数不能用于列名或表名。)参数采用以下形式之一:
- ?
- ?NNN
- :AAA
- $AAA
- @AAA
在上面的示例中,NNN是一个整数值, AAA是一个标识符。参数最初的值为 NULL。在第一次调用sqlite3_step()之前或在sqlite3_reset()之后立即调用,应用程序可以调用 sqlite3_bind()接口将值附加到参数。每次调用sqlite3_bind()都会 覆盖同一参数上的先前绑定。
允许应用程序预先准备多条 SQL 语句,并根据需要对其进行评估。对未完成的准备好的语句的数量没有任意限制 。一些应用程序在启动时多次调用sqlite3_prepare()以创建它们将永远需要的所有准备好的语句。其他应用程序保留最近使用的准备语句的缓存,然后在可用时 重用缓存中的准备语句。另一种方法是仅在循环内重用准备好的语句。
7.配置SQLite
SQLite 的默认配置适用于大多数应用程序。但有时开发人员想要调整设置以尝试挤出更多的性能,或者利用一些鲜为人知的功能。
sqlite3_config()接口用于为 SQLite 进行全局的、进程范围的配置更改 。必须在创建任何数据库连接之前调用sqlite3_config ( )接口。sqlite3_config()接口 允许程序员做如下事情:
- 调整 SQLite进行内存分配的方式,包括设置适用于安全关键型实时嵌入式系统和应用程序定义的内存分配器的替代内存分配器。
- 设置进程范围的错误日志。
- 指定应用程序定义的页面缓存。
- 调整互斥锁的使用,使它们适用于各种 线程模型,或替代应用程序定义的互斥锁系统。
在进程范围的配置完成并创建数据库连接后 ,可以使用调用sqlite3_limit()和sqlite3_db_config()来配置单个数据库连接。
8.扩展 SQLite
SQLite 包含可用于扩展其功能的接口。此类例程包括:
- sqlite3_create_collation()
- sqlite3_create_function()
- sqlite3_create_module()
- sqlite3_vfs_register()
sqlite3_create_collation()接口用于创建 用于排序文本的 新整理序列。sqlite3_create_module()接口用于注册新的 虚拟表实现。sqlite3_vfs_register()接口创建新的VFSes。
sqlite3_create_function()接口创建新 的SQL 函数——标量或聚合。新功能实现通常使用以下附加接口:
SQLite 的所有内置 SQL 函数都是使用完全相同的接口创建的。请参阅 SQLite 源代码,特别是 date.c和 func.c源文件以获取示例。
共享库或 DLL 可用作SQLite 的可加载扩展。
九、其他接口
本文仅提及最重要和最常用的 SQLite 接口。SQLite 库包括许多其他实现此处未描述的有用功能的 API。在C/C++ Interface Specification中可以找到构成 SQLite 应用程序编程接口 的完整函数列表。有关所有 SQLite 接口的完整和权威信息,请参阅该文档。