1.1应用示例
在这一部分我将展示一些简单的应用程序来说明sqlite的众多特性。这些应用程序将在下面的一些子部分中展示
1.1.1 一个sqlite应用示例
让我们通过学习一个很简单的应用程序来开始我们sqlite大陆的探险吧。下面的例子展示了一个典型的sqlite应用程序。它是一个使用sqlite API来处理一个sqlite数据库文件的C程序。
这是一个典型的sqlite应用程序:
#include <stdio.h> #include "sqlite3.h"
int main(void) { sqlite3* db = 0; sqlite3_stmt* stmt = 0; int retcode; retcode = sqlite3_open("MyDB",&db); if (retcode != sqlITE_OK){ sqlite3_close(db); fprintf(stderr,"Could not open MyDB/n"); return retcode; } retcode = sqlite3_prepare(db,"select SID from Students order by SID", -1,&stmt,0); if (retcode != sqlITE_OK){ sqlite3_close(db); fprintf(stderr,"Could not execute SELECT/n"); return retcode; } while (sqlite3_step(stmt) == sqlITE_ROW){ int i = sqlite3_column_int(stmt,0); printf("SID = %d/n",i); } sqlite3_finalize(stmt); sqlite3_close(db); return sqlITE_OK; }
|
你可以编译上面的例子并且执行它。在这个文档中显示的示例输出是在一个linux机器上获得的,但是这些例子能够在sqlite运行的其他的平台上工作
这些例子假定你已经准备了可执行的sqlite3,libsqlite3.so(windows上是sqlite3.dll而Mac OS X上是libsqlite3.dylib)共享库,和sqlite3.h接口定义文件。你可以从http://www.sqlite.org上获取这些源代码或二进制形式的文件。你会发现如果你将所有这三个(sqlite3,the shared library,和sqlite3.h)和范例放在同一个目录下处理该范例会比较容易。
举个例子,假设你在一个Linux系统上,并且你将app1.c示例程序保存在libsqlite3.so,sqlite3和sqlite3.h同一个目录下。你能够通过执行这条命令编译文件:
gcc app1.c -o ./app1 -lsqlite3 -L. |
它将会在当前工作的目录下产生一个名为app1的二进制文件。你可以执行这个二进制文件来查看输出。
注: |
如果你已经将sqlite作为一个包安装了,或者如果你的操作系统预安装了sqlite,你可能需要使用一组不同的编译参数。例如,在Ubuntu上,你可以通过命令sudo aptitude install sqlite3 libsqlite3-dev安装sqlite,并且你可以使用命令cc app1.c -o ./app1 -lsqlite3来编译应用程序。 因为在现行的Mac OS X版本中包含sqlite,上述的相同的编译命令也能工作。 |
这个应用程序打开了在当前工作目录下的MyDB数据库文件。这个数据库需要至少一个表,命名为Students;这个表必须至少有一个整型列名为SID。在下一个例子中,你将会学习如何在数据库中创建新的表,和如何在表中插入行(也被称为元组和记录),但是在目前,你可以使用这些命令创建并落户表:
sqlite3 MyDB "create table students (SID integer)" sqlite3 MyDB "insert into students values (200)" sqlite3 MyDB "insert into students values (100)" sqlite3 MyDB "insert into students values (300)" |
如果你现在运行app1(在linux系统下要引入sqlite库,,你可能需要在LD_LIBRARY_PATH环境变量中加入你的工作目录名字,你将会看到下面的输出:
SID = 100 SID = 200 SID = 300 |
注: |
在Linux,Unix和Mac OS X中,在命令提示符中键入app1的名字时,你可能需要前缀./ ./app1 |
应用程序首先做好准备工作,接着执行sql语句:select SID from Students order by SID。然后它进阶到作为结果的行集,一个接一个的获取SID的值,并且打印各个值。最后关闭数据库。
sqlite是一个调用级别上的接口库,它能够嵌入到应用程序中。该库将所有的sqlite API函数实现为C函数。所有的API函数都是以sqlite3_前缀命名,并且在sqlite3.h中声明。在示例应用程序中使用了他们中的一部分,他们是sqlite3_open,sqlite3_prepare,sqlite3_step,sqlite3_column_int,sqlite3_finalize,和 sqlite3_close。应用程序也采用了助记符常量,即用于API的返回比较值的sqlITE_OK 和 sqlITE_ROW。这些助记符在sqlite3.h中被定义。
1.1.1.1 sqlite3_open
通过执行sqlite3_open函数,应用程序经由sqlite库打开了一个到数据库文件的新连接。(该应用程序可能有其他到相同的或者不同的数据库的开放连接。sqlite清楚地处理这些连接,并且他们在sqlite注意前是相互间独立的)。如果文件还不存在,sqlite将自动的创建数据库文件。
注: |
sqlite3_open函数经由一个形参(db,在前面的例子中)返回一个连接句柄(一个指向sqlite3类型的对象的指针),而句柄被用来支持在数据库连接(因为这次打开连接)上的进一步操作。句柄表示了这次连接的完整情况。
1.1.1.2 sqlite3_prepare
sqlite3_prepare函数编译了一个sql语句,并且产生了一个等价的内部对象。这个对象在数据库文法中作为一个准备语句被普遍的提及,在sqlite中他被实现为一个字节编码程序。字节编码程序是在虚拟机或者解释器上运行的sql语言的一个抽象表示。想要得到更多的信息,看后面的部分字节编码编程语言。在本书中,我将交替使用条件字节编码程序和准备语句。
sqlite3_prepare函数经由一个形参(在前面例子中的stmt)返回一个状态句柄(指向sqlite3_stmt类型对象的指针),该句柄被用来支持进一步的操作来操纵准备状态。在这个示例程序中,我准备了select SID from Students order by SID语句作为stmt句柄。这个句柄动作起来就像一个开放的光标并且他被用来获取SELECT语句返回的作为结果的行集,一次一行。
1.1.1.3 sqlite3_step
sqlite3_step函数将执行字节编码程序直到它遇到折点(因为它已经计算了新的一行),或者直到它停止(没有剩下的行了)。在之前的例子中,他返回了sqlITE_ROW,而在之后的例子中是sqlITE_DONE。因为有的sql语句不返回行(例如UPDATE,INSERT,DELETE,和CREATE),当没有行要处理时,他总是返回sqlITE_DONE。Step函数移动指针的位置来获得SELECT语句的结果。初始的,指针指向输出行集的第一行的前一位置。执行一次step函数,指针移动到了输出行集的下一行。该指针只能向前移动。
1.1.1.4 sqlite3_column_int
如果step函数返回了sqlITE_ROW,你能够通过执行sqlite3_column_*API函数来检索每一列(也被认为是属性或域)的值。sql/sqlite和C语言中的阻抗(数据类型)的不匹配能够被自动的处理:API在两种语言间,将数据进行从存储类型到请求类型的转换。在示例应用中,每个输出行是一个整型值,我们通过执行返回整型值的sqlite3_column_int函数来读取的SID的值。
1.1.1.5 sqlite3_finalize
sqlite3_finalize函数销毁准备好的状态。也就是说,擦除字节编码程序,并且释放分配给状态句柄的所有资源。句柄变为不可用。
1.1.1.6 sqlite3_close
sqlite3_close函数关闭数据库连接,并且释放了分配给该连接的所有资源。该连接句柄变为不可用。
1.1.1.7 其他有用的函数
其它被广泛使用的API是sqlite3_bind_*和sqlite3_reset。在一个sql语句字符串(输入到sqlite3_prepare),一个或者多个文本值能够被sql参数标识?(或者?NNN,:AAA,@AAA或者$AAA,其中NNN是一个数字,而AAA是一个标示符)来代替。他们成为准备语句的输入参数这些参数的值可以通过使用bind API函数来设置。如果一个参数没有值约束,那么它不是取默认值,就是在没有默认值被声明的时候取sql NULL。reset API函数通过一个异常将状态句柄(例如,准备状态)重置回它的初始状态:所有有制约值的参数保持他们的原值。状态准备被应用程序再一次的执行,并且在再执行过程中重用这些值。然而,应用程序可能会在它开始重新执行的前再一次的执行bind API获得新值来代替前值。
1.1.1.8 返回值
所有的API函数返回0或者负整数值。sqlite推荐使用助记符来核对返回值。返回值sqlITE_OK表示成功。sqlITE_ROW表示sqlite3_step函数在SELECT语句返回的行集中找到了新的一行;sqlITE_DONE表示语句执行完成了。