Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1325988
  • 博文数量: 436
  • 博客积分: 7854
  • 博客等级: 少将
  • 技术积分: 3225
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-18 16:30
文章分类

全部博文(436)

文章存档

2013年(2)

2012年(56)

2011年(70)

2010年(308)

分类:

2010-07-25 13:41:34

Sqlite3是一个小巧的轻量级数据库,而且提供了C接口。
如果我们想使用SQL进行本地数据存储,SQlite无疑是一个非常好的工具。
下面是quick start实例。
 
 =====================================================
 
#include #include static int callback(void *NotUsed, int argc, char **argv, char **azColName){ int i; for(i=0; i
   
============================================================
 
可以看到,SQL访问数据库的非常方便。只需要简单的三个函数。
 
sqlite3_open(char* szDbFileName, sqlite3 ** db) 
sqlite3_exec(sqlite3 *db, char* szSqlCMD, callback, 0, char **zErrMsg)
sqlite3_close(sqlite3 *db)
static int callback(void *NotUsed, int argc, char **argv, char **azColName)
 
 注意有些行参是两个星.
需要解释的关键是
sqlite3_exec(sqlite3 *db, char* szSqlCMD, callback, void *NotUsed, char **zErrMsg)
执行一条SQL语句,并且,每返回一个结果,就执行一次 callback 函数
方便我们对查询到的数据进行处理。
看一下回调函数callback。必须是static的, 可以是类的成员函数。
其中的形参argc, argv, azColName是sqlite_exec帮我们填写的。
argc是查询语句返回的字段数目
argv是查询到的一条记录的各个字段
zaColName是每一列的域名
比如这样一张表MYTABLE
ID	NAME	ADDRESS	AGE
1	trulyliu	ShangHai	25
2	sunfyer	ShangHai	25
执行 select * from MYTABLE 
当查询到第一条纪录,回调被运行时
argc = 4 总共4个字段
argv[0] 	argv[1] 	argv[2] 	argv[3] 的值分别是
1	trulyliu	ShangHai	25
 
zaColName[0]	zaColName[1]	zaColName[2]	zaColName[3] 的值
ID		NAME		ADDRESS		AGE
 
第二条记录被查询到时
argc = 4 总共4个字段
argv[0] argv[1] argv[2] argv[3] 的值分别是
1 trulyliu ShangHai 25
 
zaColName[0] zaColName[1] zaColName[2] zaColName[3] 的值
ID NAME ADDRESS AGE
 
注意,查询到的这些值都是char*类型,可能需要做类型转换,以满足我们的要求。
再来看sqlite3_exec()和callback()都具有的一个形式参数,void *NotUsed,这个参数用处非常大。
不过例子把它设成了0, 没有利用上。我们可以把传递一个对象的指针进取,到了callback函数中,
再把void * 强制转换成 原来的类型,然后来进行一列操作,比如压栈。
 
下面我来举一个例子。
 
===========================================================
class A
{
public:
A:A();
 
typedef
{
int ID;
int AGE;
string NAME;
string ADDRESS;
}Info;
 
private:
 
vector InfoList;
int getDB();
static int callback(void *pvoid, int argc, char **argv, char **azColName);
 
}
 
我们的目的是把上面那个表,存储到vector Info中。
如果不利用那个void*行参,我们就需要申请全局变量。这样做是比较危险的。
下面看看阿朱教我做法。
int A::callback(void *pvoid, int argc, char **argv, char **azColName)
{
//!首先判断以下argc, 如果查询到纪录的字段数目有问题,就不用再处理下去了。
........
//!然后判断argv[0], argv[1], argv[2], argv[3]数据是否有效。如果无效,做相应处理。代码略
........
//!暂时存储
Info tmpInfo;
tmpInfo.ID = atoi(argv[0]); //!将字符串转为int
tmpInfo.AGE = atoi(argv[3]);
tmpInfo.NAME = argv[1];
tmpInfo.ADDRESS = argv[2];
 
//!巧妙的一步,讨厌回调函数的朋友, 是不是讨厌的没有理由?全局变量再也不用了
A* pA = (A*) pvoid;
 
//!将暂存纪录推入vector
A->InfoList.push_back(tmpInfo);
 
//!完成工作
return 0;
}
 
int A::getDB()
{
sqlite3 *db;
......
sqlite3_open(....);
.......
//!这里传递的是this指针,当然也可以传&InfoList。那样callback中做一点小变动就行了。
sqlite3_exec(db, SqlCMD, callback, this, &zErrMsg);
.......
sqlite3_close(db);
 
return 0;
}
 
 
A::A()
{
//!清除列表
InfoList.clear();
 
//!读取数据库并将数据放到vector InfoList中。
getDB();
}
 
=========================================================== 
阅读(5864) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~