SQLite C/C++接口介绍

这篇文章是使用SQLite C/C++接口的一个概要介绍和入门指南。

由于早期的SQLite只支持5个C/C++接口,因而非常容易学习和使用,但是随着SQLite功能的增强,新的C/C++接口不断的增加进来,到现在有超过150个不同的API接口。这往往使初学者望而却步。幸运的是,大多数SQLite中的C/C++接口是专用的,因而很少被使用到。尽管有这么多的调用接口,核心的API仍然相对简单和便于调用。本片文章的目的就是为了能够更易于理解SQLite的运作提供基础的知识。

另一篇独立的文档《The SQLite C/C++ Interface》对SQLite中的所有C/C++接口提供了详细的使用说明。一旦读者理解了SQLite的基本操作原理,这篇文档就应当作为一本参考手册。本篇文章仅仅是SQLite的一个入门介绍,而不是完整和权威性的SQLite API参考指南。

1.0 核心对象和接口

SQL数据库引擎的最主要任务是解析SQL语句。为了达成这个目的,开发者需要了解两个对象:

* 数据库连接对象:sqlite3
* 预处理语句对象:sqlite3_stmt

严格来讲,预处理语句对象并不是必须的,因为能够使用sqlite_exec或者sqlite3_get_table这些便于使用的封装接口,而这些接口封装并隐藏了预处理语句对象。尽管如此,对预处理对象的理解有助于我们更充分的使用SQLite。

数据库连接对象和预处理对象是由下列的一组C/C++接口调用操纵的:

* sqlite3_open()
* sqlite3_prepare()
* sqlite3_step()
* sqlite3_column()
* sqlite3_finalize()
* sqlite3_close()

这6个C/C++接口例程和上述的两个对象构成了SQLite的核心功能。开发者对于它们的理解能够更好的使用SQLite。

注意,这个接口例程列表更多是概念上的意义而不是实际的接口。许多这些接口都出现在各个版本之中。例如,上述列表中的sqlite3_open()例程实际上有三个不同的接口以略微不同的方式实现相同的功能:slqite3_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语句进行的预处理。

注意新的应用中不建议使用sqlite3_prepare(),而应该使用另一个接口sqlite3_prepare_v2()。

* sqlite3_step() 该接口用于解析一个由先前通过sqlite3_prepare()接口创建的预处理语句,直至返回第一列结果为止。通过再次调用sqlite3_step()可以返回下一列的结果,继续不断地调用sqlite3_step()直至整个语句完成为止。对于那些并不返回结果的语句(例如:INSERT,UPDATE,DELETE语句)一次调用sqlite3_step()就完成了语句的处理。

* sqlite3_column() 该接口返回一个由sqlite3_step()解析的预处理语句结果集中当前行的某一列数据。每次执行sqlite3_step()都返回一个新的结果集中的一行。可以多次调用sqlite3_column()接口返回那一行中所有列的数据。就像上面所说的那样,SQLite API中并没有sqlite3_column()这样的接口。取而代之的是一组用于从结果集中查询出各个列项各种数据类型数据的函数接口。在这组函数接口中,有些接口返回结果集的大小,有些返回结果集的列数。

  *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()创建的数据库连接。所有与该连接相关的预处理语句都必须在关闭连接之前销毁。

1.1 核心函数和对象的典型使用

任何使用SQLite数据库的应用在初始化期间都会典型地调用sqlite3_open()接口创建一个数据库连接。需要注意的是sqlite3_open()既能够用于打开一个已存在的数据库文件,也能够用于创建并打开一个新的数据库文件。尽管许多应用只使用一个数据库连接,但是没有理由不允许一个应用程序多次调用sqlite3_open()以创建多个针对相同或者不同数据库的数据连接。有时一个多线程应用程序会为每个线程创建独立的数据库连接。同时也需要注意的是没有必要为了访问两个或更多的数据库而创建多个独立的数据库连接。通过一次性地使用ATTACH SQL命令可以创建一个同时访问两个或更多数据库的数据库连接。

许多应用程序在退出的时候调用sqlite3_close()接口销毁它们的数据库连接。例如,一个应用程序在响应文件->打开菜单项操作的时候打开数据库连接,并在响应文件->关闭菜单项操作的时候销毁相应的数据库连接。

一个应用程序可以通过执行以下几个步骤执行一条SQL语句:

(1) 使用sqlite3_prepare()创建一个预处理语句。
(2) 重复调用sqlite3_step()解析执行预处理语句。
(3) 对于查询操作,两次调用sqlite3_step()之间通过sqlite3_column()接口查询返回的结果。
(4) 最后,使用sqlite3_finalize()销毁预处理语句。

上述就是有效使用SQLite所需要知道的知识,其余的仅仅是些需要补充的细节而已。

2.0 核心函数的方便封装接口

sqlite3_exec()接口是执行上述四个步骤的一个方便的应用调用封装接口,传递给sqlite3_exec()的回调函数用于处理每一列返回的结果集。sqlite3_get_table()接口也是另一个具备相同功能的封装接口,与sqlite3_exec()不同之处在于该接口将查询返回的结果保存在内存的堆当中而不是调用一个回调函数去处理返回结果。

需要意识到的一点是sqlite3_exec()和sqlite3_get_table()接口并未实现比核心函数更多的功能,实际上,这些封装接口完全是由这些核心接口实现的。

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

前面的讨论中,在每次执行一条SQL语句时,都经过预处理、解析执行、销毁等步骤。然而,SQLite允许相同的预处理语句被多次的解析执行,这可以通过下面的接口来实现:

* sqlite3_reset()
* sqlite3_bind()

在调用一次或多次的sqlite3_step()完成一个预处理语句的解析之后,可以通过调用sqlite3_reset()来重置该预处理语句并继续解析执行。调用sqlite3_reset()重置一个已创建的预处理语句而不是创建一个新的预处理语句避免了对sqlite3_prepare()不必要的调用。在许多的SQL语句中,执行sqlite3_prepare()的时间等于甚至超过了sqlite3_step()执行时间。因此,避免对sqlite3_prepare()频繁调用能够极大的执行的效率和性能。

但是,通常来说重复执行相同的SQL语句并没有实际的意义,更常见的情况是想重复执行类似的语句。例如,你可能想要通过多次执行INSERT语句往表中插入不同的数据。为了适应这种应用的灵活性,SQLite允许SQL语句在包含参数,并在解析执行前与实际的值进行绑定。这样,当绑定的值改变后,与新值绑定的同样的预处理语句就被再次的解析执行。

SQLite在任何地方包含一个字符串常量,你可以使用下列形式的任何一个参数:

* ?
* ?NNN
* :AAA
* $AAA
* @AAA

在上面的例子中,NNN是一个整数值而AAA是一个标示符。一个参数的初始化值是NULL。在首次调用sqlite3_step()之前或在sqlite3_reset()之后,应用程序可以调用sqlite3_bind()这组函数中的任何一个接口绑定参数与实际值。每次对sqlite3_bind()调用就会覆盖之前与该参数绑定的值。

一个应用程序允许实现准备多条预执行的SQL语句并在需要的时候执行,并没有对预处理语句的数量有特别的限制。

4.0 扩展SQLite

SQLite包含一些可用于扩展其功能的一些其他接口,这些接口包括:

* sqlite3_create_collation()
* sqlite3_create_function()
* sqlite3_create_module()

sqlite3_create_collation()接口用于为索引文本创建新的对照序列。sqlite3_create_module()接口用于注册新的续表实现接口。

sqlite3_create_function()接口创建新的SQL函数-即可以是单一的也可以是组合的接口。新的函数实现通常利用下列的辅助接口:

* sqlite3_aggregate_context()
* sqlite3_result()
* sqlite3_user_data()
* sqlite3_value()

SQLite中所有内建的SQL函数接口也是通过这些相同的接口实现的。查看SQLite源代码,尤其是date.c和func.c两个文件就有许多这方面的例子。

5.0 其他接口

本篇文章仅提到了基础的SQLite函数接口,SQLite库包含了许多其他有用特性的API接口实现,但在这里并未描述。一个完整的SQLite应用编程接口文档可以在C/C++ Interface Specification找到。可以参考这份文档以获得完整和权威的SQLite接口介绍。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/kevin4218/archive/2009/09/03/4515506.aspx