准备工作:
主机环境:虚拟机下Fedora9
交叉编译器:arm-linux-gcc-4.4.3
软件包:sqlite-3.6.18.tar.bz2
把sqlite-3.6.18.tar.bz2解压到主机的/nfs_dir/目录下,并重命名为sqlite,在同一级目录下在新建目录sqlite_arm,这个目录来放编译后产生的文件。
二.配置SQLite
在sqlite目录终端下进行如下配置:
./configure --prefix=/nfs/sqlite/sqlite_arm --disable-tcl --host=arm-linux
make
make install
经 过上述的命令将编译好的文件安装到sqlite-arm目录下,在sqlite-arm目录下会生成bin、lib、include目录,bin目录下是 sqlite3可执行文件,lib目录下包含运行sqlite3所依赖的库,include目录下是sqlite的C语言API的头文件,编程时会用到。
三.移植
分别将bin下的文件下载到开发板的/usr/bin目录中,lib下的所有文件下载到开发板的/usr/lib目录中即可。注意这里说的是所有。包括符号连接,即一个不留:
cp –dr ./lib/ /usr/lib/
四.登录开发板的Linux,执行:
sqlite3 demo.db
sqlite3是一个sqlite的命令行访问程序,demo.db是新建的数据库的名字,必须以db作后缀。如果能进行下边的操作说明一切OK.
#sqlite3 test.db |
这里以SQLite官方站点http://sqlite.org的quick start文档中的测试程序为例对移植到ARM-Linux上的SQLite3进行测试。该程序清单如下:
#include <stdio.h> #include <sqlite3.h> static int callback(void *NotUsed, int argc, char **argv, char **azColName) { int i; for(i=0; i<argc; i++){ printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL"); } printf("\n"); return 0; } int main(int argc, char **argv) { sqlite3 *db; char *zErrMsg = 0; int rc; if( argc!=3 ){ fprintf(stderr, "Usage: %s DATABASE SQL-STATEMENT\n", argv[0]); } rc = sqlite3_open(argv[1], &db); if( rc ){ fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db)); sqlite3_close(db); } rc = sqlite3_exec(db, argv[2], callback, 0, &zErrMsg); if( rc!=SQLITE_OK ){ fprintf(stderr, "SQL error: %s\n", zErrMsg); } sqlite3_close(db); return 0; } |
使用如下命令编译测试程序:
arm-linux-gcc -o test test.c -lsqlite3 -L/nfs/sqlite/sqlite_arm/lib -I/nfs/sqlite/sqlite_arm/include
使用如下命令去掉调试信息:
arm-linux-strip test
六.在上面新建的数据库目录下测试:
#./test_sqlite test.db "select * from film"
应该会看到如下的结果:
number = 1
name = aaa
number = 2
name = bbb
好 了,挺简单的吧,sqlite也是一个关系性数据库,可以做的其实也是比较少的,或者说要学的新东西还是挺少的,以前的数据库连oracle,DB2都玩 的转,何况这个小家伙,塞牙缝都不够啊.下节我们会讲讲sqlite3中的一些基本的编程接口,有了这些接口,C编程问题还不是手到擒来啊.
嵌入式数据库SQLite3相关操作---操作接口篇
在上节中,我们介绍了有关SQLite3移植到开发板的过程,这节就大家总结了一下SQLite3提供的C语言编程接口,以供大家编程时使用方便。
首先要说明的是。sqlite3本身是提供了一些命令来操作数据库的。为了与SQL语句相区别,他们都是以小数点.开头。可以用
.help 获取相关命令
一,打开和关闭数据库
使用SQLite3接口操作数据库时都要先打开数据库,有点多余啊,哪个数据库不是呢?嘿嘿
int sqlite3_open(const char *filename, sqlite3 **ppDb); |
参数即返回值意义如下:
filename:要打开的数据库的文件名
ppDb:用户返回数据库句柄
返回值:SQLITE_OK代表成功,否则为错误码
其实返回的错误码可以在SQLite3源码的sqlite3.h头文件找到,这里就不说了。需要说明的是这些错误是SQLite3编程接口共同使用的。而不是sqlite3_open函数私有。
用完了,当然要关闭:
int sqlite3_close(sqlite3 *ppDb); |
二,执行SQL语句
SQLite3提供了一个一般化的编程接口,可以对以打开的数据库执行任何SQL语句。这个函数的原型如下:
int sqlite3_exec(sqlite3 *pDb, const char *sql, int (*callback)(void* context, int nArg, char** azArg, char** azCol), void *context, char **errmsg); |
参数即返回值意义如下:
pDb:已打开的数据库的句柄
sql:字符串,内容是一条或多条sql语句
callback:回调函数
context:传递给回调函数的第一个参数,可称上下文参数
errmsg:指向一个字符串,其内容是对操作中发生的错误的文字描述
返回值:SQLITE_OK代表成功,否则为错误码
回调函数的作用是:当进行查询操作时,每查询到一条记录都会调用一次回调函数,这条记录的内容通过回调函数的参数传入。回调函数的参数既返回值的含义解释如下:
context:调用sqlite3_exec时传入的context指针。
nArg:数据的个数
azArg:字符串数组,有nArg个元素,表示每个字段的值
azCol:字符串数组,有nArg个元素,表示每个字段的名称
返回值:0表示要继续查询否则查询操作结束,对sqllite3_exe函数的调用将返回错误码SQLITE_ABORT.
即使记录中某个字段的类型为整数,它的值也是由C语言的字符串来代表中。
还 有就是errmsg参数是一个字符指针变量的地址,通过它将得到一个字符串的首地址。显然,这个字符串的存储空间是在sqlite3_exec函数内动态 分配得到的,因此用过后必须释放以免造成内存泄漏。鉴于外界并不知道sqlite3_exe函数内部是如何进行内存分配的。SQLite3平台专门提供了 一个函数用于释放这块内存,其原型如下:
void sqlite3_free(void *p); |
其中参数P指向要释放的内存。
三.查询数据库
其实呢,使用上面的sqlite3_exec函数就可以对数据库进行查询操作,但它使用回调函数作为返回结果的手段,有时不是很方便,因此SQLite3也提供了一个专门的接口进行查询操作,其函数原型如下:
sqlite3_get_table(sqlite3 *pDb, const char *sql, char ***pResult, int *nrow, int *ncolumn, char **errmsg); |
其中各个参数的含义解释如下:
pDb:已打开的数据库的实例
sql:字符串,内容是一条或多条SQL语句。
pResult:一个(char **)型变量的地址,用于返回查询结果,查询结果由字符串数组代表。
nrow:结果表的行数。
ncolumn:结果的列数
errmsg:指向一个字符串,其内容是对操作中发生的错误的文字描述
这 里的参数都好理解,不好理解的是pResult是查询的结果,它是一个字符串数组,因此它的首地址是(char **)地址。虽然它是一个一维的字符串数组,但要以二维的方式去理解,其中前ncolumn个字符串表示结果表的字段名,随后的ncolumn个字符串则 是第一条记录的各个字段的值,依次类推。
内外一个需要说明的问题就是空间的问题,显然pResult所指向的字符串数组及各个字符串所占 的空间都是在sqlite3_get_table函数内部动态分配得到的。因此需要使用后进行释放。由于它又不是一块平坦的内存,故也不能用 sqlite3_free函数来释放,而必须用下面这个专用的函数:
void sqlite3_free_table(char **result); |