当前位置: 代码迷 >> SQL >> SQLite3学习之根本SQL语法使用-wince6.0
  详细解决方案

SQLite3学习之根本SQL语法使用-wince6.0

热度:9   发布时间:2016-05-05 12:56:27.0
SQLite3学习之基本SQL语法使用-wince6.0

说明:应用和测试均在以下环境中运行通过

本项目是在VS2005下,C++语言,sqlite3.7.14版本,开发板mini2440,wince6.0

 工程先拷贝:WinceSQLite_DLL.lib,WinceSQLite_DLL.dll,sqlite3.h和数据库文件Temp-Humi.db,到对应的工程文件中

 

SQLite 3.0提供了很多API函数,还有一些数据结构和预定义(#defines). 不过你们可以放心,这些接口使用起来不复杂. 最简单的程序仍然使用三个函数就可以完成: sqlite3_open(), sqlite3_exec(), 和 sqlite3_close(). 要是想更好的控制数据库引擎的执行,可以使用提供的sqlite3_prepare()函数把SQL语句编译成字节码,然后在使用sqlite3_step()函数来执行编译后的字节码. 以sqlite3_column_开头的一组API函数用来获取查询结果集中的信息. 许多接口函数都是成对出现的,同时有UTF-8和UTF-16两个版本. 并且提供了一组函数用来执行用户自定义的SQL函数和文本排序函数.

 

1、打开数据库函数:

int sqlite3_open(const char*, sqlite3**);

第一个参数:文件路径,注意wince下只有绝对路劲,关于如何获取wince下的绝对路径可以参考另外一篇文章:

第二个参数:是sqlite3指针的指针,用于获取打开的文件

 

2、查询数据库函数——使用回调函数

sqlite3_exec 函数依然像它在SQLite2中一样承担着很多的工作.该函数的第二个参数中可以编译和执行零个或多个SQL语句. 查询的结果返回给回调函数. 在SQLite3里,sqlite3_exec一般是被准备SQL语句接口封装起来使用的。

typedef int (*sqlite_callback)(void*,int,char**, char**);

int sqlite3_exec(sqlite3*, const char *sql, sqlite_callback, void*, char**);

第一个参数不再说了,是前面open函数得到的指针。

第二个参数const char *sql 是一条 sql 语句,以\0结尾。

第三个参数sqlite3_callback 是回调,当这条语句执行之后,sqlite3会去调用你提供的这个函数。

第四个参数void * 是你所提供的指针,你可以传递任何一个指针参数到这里,这个参数最终会传到回调函数里面,这个指针比较重要,可以用来作参数的传递。如果不需要传递指针给回调函数,可以填NULL。

第五个参数char ** errmsg 是错误信息。注意是指针的指针。sqlite3里面有很多固定的错误信息。执行 sqlite3_exec 之后,执行失败时可以查阅这个指针(直接 printf(“%s\n”,errmsg))得到一串字符串信息,这串信息告诉你错在什么地方。sqlite3_exec函数通过修改你传入的指针的指针,把你提供的指针指向错误提示信息,这样sqlite3_exec函数外面就可以通过这个char*得到具体错误提示。

说明:通常sqlite3_callback 和它后面的 void * 这两个位置都可以填 NULL。填NULL表示你不需要回调。比如你做 insert 操作,做 delete 操作,就没有必要使用回调。而当你做 select 时,就要使用回调,因为 sqlite3 把数据查出来,得通过回调告诉你查出了什么数据。

 

2、查询数据库函数——不使用回调函数 

上面介绍的 sqlite3_exec 是使用回调来执行 select 操作。还有一个方法可以直接查询而不需要回调。回调的好处是:代码可以更加整齐,但是用回调很麻烦,你得声明一个函数,如果这个函数是类成员函数,你还不得不把它声明成 static 的(因为C++成员函数实际上隐藏了一个参数:this,C++调用类的成员函数的时候,隐含把类指针当成函数的第一个参数传递进去。结果,这造成跟前面说的 sqlite 回调函数的参数不相符。只有当把成员函数声明成 static 时,它才没有多余的隐含的this参数)。

不使用回调函数,可以通过 sqlite3_get_table 函数查询

int sqlite3_get_table(sqlite3*, const char *sql, char ***resultp, int *nrow, int *ncolumn, char **errmsg );

第一个参数不再多说,看前面的例子。

第二个参数是 sql 语句,跟 sqlite3_exec 里的 sql 是一样的。是一个很普通的以\0结尾的char *字符串。

第三个参数是查询结果,它依然一维数组(不要以为是二维数组,更不要以为是三维数组)。它内存布局是:第一行是字段名称,后面是紧接着是每个字段的值。

第四个参数是查询出多少条记录(即查出多少行)。

第五个参数是多少个字段(多少列)。

第六个参数是错误信息。

工程文件,源代码下载http://download.csdn.net/detail/mjx91282041/4743958

测试代码:

 

         sqlite3 *db;//	int rc;	char *zErrMsg;//sqlite执行错误返回的字符指针		//打开sqlite的数据库文件,	//特别说明:若找不到文件,sqlite会自己创建一个同名db文件	rc = sqlite3_open("Program Files\\WinceSQliteTest2\\Temp-Humi.db", &db);	if( rc != SQLITE_OK ){		sqlite3_close(db);		printf("The sqlite3 database open error!");	}	//插入数据,两种格式都行,ID为primary	//char *pStr = "INSERT INTO SensorData(ID,SensorID,温度,湿度,Time)values( NULL,1003, 31.0, 23.5, '20120501421900')" ;	char *pStr= "INSERT INTO \"SensorData\" values( NULL, 1003,31.0, 23.5, '20120501421900');" ;	rc = sqlite3_exec( db , pStr , 0 , 0 , &zErrMsg );	if (rc==SQLITE_OK)	{		printf("Insert data to the Temp-Humi.db successed");	}else		printf("插入记录失败,错误码:%d,错误原因:%s\n", rc, zErrMsg );	//查询数据库有两种方式,回调函数和非回调函数	//使用回调函数	//	rc = sqlite3_exec( db, "select SensorID,time from SensorData", SQLiteQueryResultCallBack, NULL, &zErrMsg );	//查询数据,不使用回调函数     char** pResult;     int nRow;     int nCol;     rc = sqlite3_get_table(db, "select SensorID,time from SensorData",&pResult,&nRow,&nCol,&zErrMsg);     if (rc != SQLITE_OK)     {         sqlite3_close(db);         sqlite3_free(zErrMsg);           }//网上的显示例子	/* string strOut;	 int nIndex = nCol;	 for(int i=0;i<nRow;i++)	 {		 for(int j=0;j<nCol;j++)		 {			 strOut+=pResult[j];			 strOut+=":";			 strOut+=pResult[nIndex];			 strOut+="\n";			 ++nIndex;		 }	 }	 sqlite3_free_table(pResult);	 cout<<strOut<<endl;	*/	//理解内存布局后自己写的显示	//pResult的内存布局是:字段名称,后面是紧接着是每个字段的值	 int nIndex = nCol;	 for(int i=0;i<nRow;i++)	 {		 for(int j=0;j<nCol;j++)		 {			 printf("%s:%s\r\n",pResult[j],pResult[nIndex++]);		 }	 }	 sqlite3_free_table(pResult);	// 关闭数据库	sqlite3_close( db );