1.摘要
以下介绍的两个对象和八种方法构成了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 ()→一个便利封装接口。它被允许执行一行或一串命令( sqlite3_prepare ()、sqlite3_step ()、sqlite3_column ()和sqlite3_finalize () ),并可以通过回调接口收集所有的返回数据。
2.简介
SQLite 拥有超过 225 个 API。但是,大多数 API 都是可选的,非常专业化,初学者可以忽略这些 API。而核心API很小,很简单,很容易学习。故本文主要总结了核心API的相关文档供初学者学习。
另一份文件,SQLite C/C++接口,为SQLite的所有C/C++API提供了详细的规范。倘若读者了解了 SQLite 的操作基本原则,该文档则可用作参考指南。本文仅用作介绍,即不是 SQLite API 的完整或权威参考。
3.核心对象和接口
SQL数据库引擎的主要任务是评估SQL中的SQL语句。要做到这一点,开发人员需要两个对象:
严格地说,预处理语句对象不是必需的,因为可以使用便利封装接口sqlite3_exec ()或sqlite3_get_table (),而且这些便利封装接口封装和隐藏了预处理语句对象。然而,要充分利用SQLite,还需要了解预处理语句。
数据库连接对象和预处理语句对象由下面列出的一小组C/ C++接口例程控制:
- sqlite3_open ()
- sqlite3_prepare ()
- sqlite3_step ()
- sqlite3_column ()
- sqlite3_finalize ()
- sqlite3_close ()
注意,上面的例程列表是概念性的,而不是实际的。其中许多例程有多个版本。例如,上面的列表显示了一个名为 sqlite3_open ()的例程,而实际上有三个独立的例程以略微不同的方式完成相同的事情: sqlite3_open ()、sqlite3_open16()和sqlite3_open_v2()。列表中提到sqlite3_column (),但实际上并不存在这样的例程。列表中显示的"sqlite3_column()"是一个占位符,用于在各种数据类型中增加列数据的整个例程。
以下是核心界面功能的总结:
-
sqlite3_open ()
这个例程打开一个到SQLite数据库文件的连接,并返回一个数据库连接对象。这通常是应用程序的第一个SQLite API调用,也是大多数其他SQLite API的先决条件。许多SQLite接口需要一个指向数据库连接对象的指针作为它们的第一个参数,并且可以看作是数据库连接对象上的方法。这个例程是数据库连接对象的构造函数。 -
sqlite3_prepare ()
这个例程将SQL文本转换为预处理语句对象,并返回指向该对象的指针。这个接口需要一个由之前调用sqlite3_open ()创建的数据库连接指针和一个包含要准备的SQL语句的文本字符串。这个API并不实际计算SQL语句。它只是为求值准备SQL语句。把每个SQL语句看作一个小型计算机程序。sqlite3_prepare ()的目的是将该程序编译为目标代码。预处理语句是目标代码。然后,sqlite3_step ()接口运行对象代码以获得结果。
新的应用程序应该总是调用sqlite3_open_v2()而不是sqlite3_prepare ()。为了向后兼容,保留了旧的sqlite3_prepare ()。但是sqlite3_open_v2()提供了一个更好的接口。
-
sqlite3_step ()
这个例程用于计算之前由sqlite3_prepare ()接口创建的预处理语句。语句的计算直到第一行结果可用为止。要前进到结果的第二行,再次调用sqlite3_step ()。继续调用sqlite3_step (),直到语句完成。不返回结果的语句(例如:INSERT、UPDATE或DELETE语句)在调用sqlite3_step ()时运行完成。 -
sqlite3_column ()
这个例程从sqlite3_step ()计算的准备语句的结果集中的当前行返回一个列。每次sqlite3_step ()以一个新的结果集行停止时,可以多次调用这个例程来查找该行中所有列的值。如上所述,在SQLite API中实际上没有“sqlite3_column()”函数。相反,我们这里所说的“sqlite3_column()”是一个占位符,用于以各种数据类型返回结果集中的值的整个函数族。这个系列中还有一些例程可以返回结果的大小(如果是字符串或BLOB)和结果集中的列数:
-
sqlite3_finalize ()
这个例程将销毁由之前调用sqlite3_prepare ()创建的预处理语句对象。为了避免内存泄漏,必须调用这个例程的来销毁每个已经完成任务的预处理语句对象。 -
sqlite3_close ()
这个例程关闭以前通过调用sqlite3_open ()打开的数据库连接对象。在关闭连接之前,应该结束与连接关联的所有预处理语句对象。
4.核心例程与对象的典型用法
应用程序通常使用sqlite3_open ()在初始化期间创建单个数据库连接对象。注意,sqlite3_open ()既可以用来打开现有的数据库文件,也可以用来创建和打开新的数据库文件。虽然许多应用程序只使用单个数据库连接对象,但应用程序没有理由不能多次调用sqlite3_open ()来打开多个数据库连接——无论是到同一个数据库还是到不同的数据库。有时,多线程应用程序将为每个线程创建单独的数据库连接对象。注意,单个数据库连接对象可以使用ATTACH SQL命令访问两个或多个数据库,因此没有必要为每个数据库文件建立单独的数据库连接对象。
许多应用程序在关闭时调用sqlite3_close ()来销毁它们的数据库连接对象。或者,例如,使用SQLite作为应用程序文件格式 的应用程序可能会打开数据库连接对象以响应File/open菜单操作,然后销毁相应的数据库连接对象以响应File/Close菜单。
要运行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的可加载扩展。
9.其他接口
本文只提到最重要和最常用的SQLite接口。SQLite库包括许多其他实现有用特性的API,这些特性在这里没有描述。形成SQLite应用程序编程接口的完整函数列表可以在C/ C++接口规范中找到。有关所有SQLite接口的完整和权威信息,请参阅该文档。