SQLite C/ C++接口简介

来自泡泡学习笔记
BrainBs讨论 | 贡献2024年12月4日 (三) 12:48的版本 (创建页面,内容为“==总结== 下面的两个对象和八个方法组成了SQLite接口的基本元素: *sqlite3→数据库连接对象。由sqlite3_open()创建,由sqlite3_close()销毁。 *sqlite3_stmt→准备好的语句对象。由sqlite3_prepare()创建,由sqlite3_finalize()销毁。 *sqlite3_open()→打开一个连接到新的或现有的SQLite数据库。sqlite3的构造函数。 *sqlite3_prepare()→将SQL文本编译成字节码,用于查询或更新数据…”)
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳到导航 跳到搜索

总结

下面的两个对象和八个方法组成了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()。


介绍

SQLite有超过225个api。然而,大多数api都是可选的,非常专门化,初学者可以忽略。核心API小,简单,易于学习。本文总结了核心API。

一个单独的文档,SQLite C/ C++接口,提供了SQLite所有C/ C++ api的详细规范。一旦读者理解了SQLite的基本操作原则,就可以将该文档用作参考指南。本文仅作为介绍,对于SQLite API既不是完整的也不是权威的参考。


核心对象和接口

SQL数据库引擎的主要任务是计算SQL的SQL语句。要实现这一点,开发人员需要两个对象:

  • 数据库连接对象:sqlite3
  • 准备好的语句对象:sqlite3_stmt


严格地说,不需要准备好的语句对象,因为可以使用方便的包装器接口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_prepare_v2()而不是sqlite3_prepare()。为了向后兼容,保留了旧的sqlite3_prepare()。但是sqlite3_prepare_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_column_blob ()
  • sqlite3_column_bytes ()
  • sqlite3_column_bytes16 ()
  • sqlite3_column_count ()
  • sqlite3_column_double ()
  • sqlite3_column_int ()
  • sqlite3_column_int64 ()
  • sqlite3_column_text ()
  • sqlite3_column_text16 ()
  • sqlite3_column_type ()
  • sqlite3_column_value ()


sqlite3_finalize ()

这个例程销毁由先前调用sqlite3_prepare()创建的预处理语句。为了避免内存泄漏,必须使用对这个例程的调用来销毁每个准备好的语句。


sqlite3_close ()

这个例程关闭先前通过调用sqlite3_open()打开的数据库连接。在关闭连接之前,应该完成与连接相关的所有准备语句。


核心例程和对象的典型用法

应用程序通常会在初始化期间使用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,上述内容是我们真正需要知道的。剩下的就是优化和细节了。


围绕核心例程的便利包装

sqlite3_exec()接口是一个方便的包装器,它通过一个函数调用执行上述所有四个步骤。传递给sqlite3_exec()的回调函数用于处理结果集的每一行。sqlite3_get_table()是另一个方便的包装器,它完成上述所有四个步骤。sqlite3_get_table()接口与sqlite3_exec()的不同之处在于,它将查询结果存储在堆内存中,而不是调用回调。

重要的是要认识到,sqlite3_exec()和sqlite3_get_table()都不能做任何使用核心例程无法完成的事情。实际上,这些包装器完全是根据核心例程实现的。


绑定参数和重用预处理语句

在前面的讨论中,假设每个SQL语句只准备一次,然后求值,然后销毁。然而,SQLite允许对相同的预处理语句进行多次求值。这是使用以下例程完成的:

  • sqlite3_reset ()
  • sqlite3_bind ()


在通过一次或多次调用sqlite3_step()对准备好的语句求值之后,它可以被重置,以便通过调用sqlite3_reset()再次求值。可以把sqlite3_reset()看作是将准备好的语句程序倒回开始。在现有的预处理语句上使用sqlite3_reset()而不是创建一个新的预处理语句,可以避免不必要地调用sqlite3_prepare()。对于许多SQL语句,运行sqlite3_prepare()所需的时间等于或超过运行sqlite3_step()所需的时间。因此,避免调用sqlite3_prepare()可以显著提高性能。

多次计算完全相同的SQL语句通常是没有用处的。更常见的是,人们想要评估类似的陈述。例如,您可能希望使用不同的值对INSERT语句进行多次求值。或者,您可能希望在WHERE子句中使用不同的键多次计算相同的查询。为了适应这一点,SQLite允许SQL语句包含在求值之前“绑定”到值的参数。稍后可以更改这些值,并且可以使用新值第二次计算相同的预处理语句。

只要查询或数据修改语句中允许使用字符串文字、blob文字、数字常量或NULL, SQLite就允许使用参数。(DQL或DML)(参数不能用于列名或表名,也不能用作约束或默认值的值。参数采用下列形式之一:

?
?NNN
: AAA
$AAA
@AAA


在上面的例子中,NNN是一个整数值,AAA是一个标识符。参数初始值为NULL。在第一次调用sqlite3_step()之前或在sqlite3_reset()之后,应用程序可以调用sqlite3_bind()接口将值附加到参数上。每次调用sqlite3_bind()都会覆盖先前对同一参数的绑定。

允许应用程序提前准备多个SQL语句,并根据需要对它们进行评估。未完成的准备语句的数量没有任意限制。一些应用程序在启动时多次调用sqlite3_prepare()来创建它们需要的所有准备好的语句。其他应用程序保留最近使用的预处理语句的缓存,然后在可用时从缓存中重用预处理语句。另一种方法是仅在循环内重用准备好的语句。


配置SQLite

SQLite的默认配置适用于大多数应用程序。但有时开发人员想要调整设置,试图挤出更多的性能,或利用一些模糊的功能。

sqlite3_config()接口用于对SQLite进行全局的、进程范围的配置更改。在创建任何数据库连接之前,必须调用sqlite3_config()接口。sqlite3_config()接口允许程序员做这样的事情:

  • 调整SQLite如何分配内存,包括设置适合安全关键型实时嵌入式系统和应用程序定义的内存分配器的替代内存分配器。
  • 设置进程范围的错误日志。
  • 指定应用程序定义的页面缓存。
  • 调整互斥锁的使用,使其适合各种线程模型,或者替换应用程序定义的互斥锁系统。
  • 在完成进程范围的配置并创建数据库连接之后,可以使用调用sqlite3_limit()和sqlite3_db_config()来配置各个数据库连接。


延长SQLite

SQLite包含可用于扩展其功能的接口。这些例程包括:

  • sqlite3_create_collation ()
  • sqlite3_create_function ()
  • sqlite3_create_module ()
  • sqlite3_vfs_register ()


sqlite3_create_collation()接口用于为文本排序创建新的排序序列。sqlite3_create_module()接口用于注册新的虚拟表实现。sqlite3_vfs_register()接口创建新的虚拟存储系统。

sqlite3_create_function()接口创建新的SQL函数——可以是标量函数,也可以是聚合函数。新的函数实现通常使用以下附加接口:

  • sqlite3_aggregate_context ()
  • sqlite3_result ()
  • sqlite3_user_data ()
  • sqlite3_value ()


SQLite的所有内置SQL函数都是使用完全相同的接口创建的。参考SQLite源代码,特别是date.c和function .c源文件以获取示例。

共享库或dll可以用作SQLite的可加载扩展。


其他接口

本文只提到最重要和最常用的SQLite接口。SQLite库包括许多其他api,它们实现了这里没有描述的有用特性。形成SQLite应用程序编程接口的函数的完整列表可以在C/ C++接口规范中找到。有关所有SQLite接口的完整和权威信息,请参考该文档。