C/C++调用sqlite3接口详解

          sqlite3的C/C++接口用法可分为两种:回调形式与非回调形式。所谓回调形式其实就是通过回调的方式处理sql语句执行结果,非回调形式就是待sql语句执行完毕后再通过返回值和相关函数来判断、获取执行结果。

一、sqlite3非回调形式接口用法

1、sqlite3_open   打开sqlite3数据库的连接 

在sqlite3数据库管理系统中,用结构体sqlite3来表示一个打开的数据库对象(sqlite3数据库连接对象),函数原型及用法如下:

int sqlite3_open(const char *filename, sqlite3 **ppDb);
filename:要打开的sqlite3数据库的路径名
ppDb: 二级指针,用来保存打开的数据库的连接对象。
返回值: 成功返回SQLITE_OK,失败返回其他值。

2、 sqlite3_close: 关闭数据库连接对象

int sqlite3_close(sqlite3*);

3、SQL语句对象
    sqlite3_stmt 这个结构体用来描述一个SQL语句对象。我们的应用都是通过SQL语句对象去发送sql指令给数据库管理系统的。 

4、sqlite3_prepare_v2:  编译SQL语句,并创建一个SQL语句对象
  

 int sqlite3_prepare_v2(
      sqlite3 *db,           // 数据库连接对象
      const char *zSql,      // 指向原始sql语句(要编译的sql语句),可以包含变量名的
      int nByte,             // < 0: 编译zSql到第一个\0为止
                             // >0:  编译zSql中前面nByte个字符
                             // =0:  什么也不编译
      sqlite3_stmt **ppStmt, // *ppStmt用来保存编译好的sql语句对象
      const char **pzTail    // *pzTail如果不为空,则*pzTail指向zSql中编译的第一条完整sql语句后面的第一个字符。                 
    );
    返回值:成功返回SQLITE_OK,失败返回其他值.

zSql指向原始的SQL语句:
(1) 不包括参数名
     "CREATE TABLE SCORE (\
        NUM INTEGER PRIMARY KEY, \
        NAME VARCHAR(255) NOT NULL,\
        SCORE INTEGER\
        );"

        char *sql = "INSERT INTO STU VALUES(2, 'HULONGTENG', 53) ;";
(2)包括参数名

        parameters: 

        编译的SQL语句中可以包含"变量/参数",其值可以在运行期间通过特定的参数接口来指定。
        char *sql = "INSERT INTO STU VALUES(变量, 变量, 变量) ;";

有如下几种方式指定变量名:

            :AAAA  命名参数,参数名为AAAA
            @AAAA 命名参数,参数名为@AAAA
            $AAAA 命令参数,参数名为$AAAA, 参数名可以包含一个或多个:: 和().

例子:
            char *sql = "INSERT INTO STU VALUES(@NUM, @NAME, @SCORE) ;";

4、给参数赋值
    (1)    获取参数索引。因为所有的绑定参数的函数,都是通过参数索引去指定参数的。
     sqlite3_bind_parameter_index用来获取zName在SQL语句对象sqlite3_stmt中的索引。

函数原型:     

int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
返回值:成功返回索引值(>0),假如没有匹配的参数名找到,则返回0

    (2) 给参数赋值: 绑定值到变量/参数

参数:  SQL语句对象,参数索引,要设置的参数值
        

int sqlite3_bind_double(sqlite3_stmt*, int , double);
int sqlite3_bind_int(sqlite3_stmt *, int , int);
int sqlite3_bind_int64(sqlite3_stmt *, int ,  sqlite3_int64);

参数: SQL语句对象,参数索引
        int sqlite3_bind_null(sqlite3_stmt* , int);

参数: SQL语句对象,参数索引,要设置的字符串指针,字符串的长度,函数指针用来释放字符串(可以为空)
        int sqlite3_bind_text(sqlite3_stmt *, int,  const char *,  int , void (*) (void *));

5、sqlite3_step: 用来执行编译好的SQL语句对象(由sqlite3_stmt指定),每次返回一行执行结果。

函数原型及用法:

int sqlite3_step(sqlite3_stmt*);
sqlite3_stmt:指向编译好的要执行的SQL语句对象
返回值: SQLITE_BUSY: 没获取到锁,语句没执行。
        SQLITE_DONE: sql语句执行完成。
        SQLITE_ERROR: 出错啦
        SQLITE_MISUSE: 使用方法不当
        SQLITE_ROW:  假如SQL语句执行有返回结果,SQLITE_ROW返回。然后调用者调用sqlite3_column解析结果。        

6、查询结果分析函数
若sql语句为SELECT语句,它的返回结果是一个结果表,则需要用额外的函数接口去获取这些结果表中的记录。

若调用sqlite3_step函数则需要判断返回值,并对执行结果表一行一行的处理,直到返回值为SQLITE_DONE为止。

int sqlite3_column_count(sqlite3_stmt *pStmt);   //返回结果行中有多少列        
int sqlite3_column_type(sqlite3_stmt *pStmt, int iCol);  //返回结果行中第iCol列的数据类型
返回值: SQLITE_INTEGER :整数类型
        SQLITE_FLOAT: 浮点类型
        SQLITE_TEXT: 文本类型,char *
        SQLITE_BLOB: blob
        SQLITE_NULL: 空类型

判断出类型后,调用如下相应类型的接口获取结果集中当前行中第iCol列的值。

const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
const char *sqlite3_column_decltype(sqlite3_stmt *, int iCol);
const void *sqlite3_column_decltype16(sqlite3_stmt *, int iCol);
double sqlite3_column_double(sqlite3_stmt*, int iCol);
int sqlite3_column_int(sqlite3_stmt*, int iCol);
long long int sqlite3_column_int64(sqlite3_stmt*, int iCol);
const char *sqlite3_column_name(sqlite3_stmt*, int iCol);
const void *sqlite3_column_name16(sqlite3_stmt*, int iCol);
const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);

也可以不通过sqlite3_step 函数来获取执行结果,使用sqlite3_get_table 函数直接获取整个结果表。

函数原型为:

int sqlite3_get_table(
  sqlite3 *db,          /* An open database */
  const char *zSql,     /* SQL to be evaluated */
  char ***pazResult,    /* Results of the query */
  int *pnRow,           /* Number of result rows written here */
  int *pnColumn,        /* Number of result columns written here */
  char **pzErrmsg       /* Error msg written here */
);
第1个参数为数据库连接对象。
第2个参数是sql 语句,跟sqlite3_exec 里的sql 是一样的。是一个很普通的以\0结尾的char*字符串。
第3个参数是查询结果(可理解为二维数组的地址)。
第4个参数是查询出多少条记录(即查出多少行,不包括字段名那行)。
第5个参数是多少个字段(多少列)。
第6个参数是错误信息
pazResult返回的字符串数量实际上是(*pnRow+1)*(*pnColumn),因为前(*pnColumn)个是字段名

使用sqlite3_get_table 函数后,需要使用对应的sqlite3_free_table函数来释放查询结果所申请的内存。函数原型:

void sqlite3_free_table(char **result); //释放掉查询结果申请的内存空间

6、sqlite3_reset:用来复位sql语句对象,以便下一轮的参数赋值

int sqlite3_reset(sqlite3_stmt *pStmt);

7、sqlite3_finalize:用来销毁一个SQL语句对象,与sqlite3_prepare_v2创建的SQL语句对象对应。

int sqlite3_finalize(sqlite3_stmt *pStmt);

使用示例一(sqlite3_step 方式获取执行结果):

#include <sqlite3.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

int main(int argc, char *argv[])
{
	sqlite3 *pdb;
	int r ;
	/*step 1: 打开数据库连接对象*/
	r = sqlite3_open(argv[1], &pdb );
	if (r != SQLITE_OK)
	{
		perror("sqlite3_open error");
		return -1;
	}
	/*step 2: sql语句对象。*/
	sqlite3_stmt *pStmt;
	char *sql=	"SELECT STUINFO.SID,SNAME,CNAME,SCORE\
					FROM STUINFO, COURCE, SCORE\
					WHERE STUINFO.SID = SCORE.SID \
					AND COURCE.CID = SCORE.CID ;";			
	r = sqlite3_prepare_v2(
				pdb, //数据库连接对象
				sql, //指向原始sql语句字符串
				strlen(sql) , //
				&pStmt,
				NULL
			);
	if (r != SQLITE_OK)
	{
		perror("sqlite3_prepare_v2 error:");
		return -1;
	}
	while (1)
	{
		static int first = 1;
		int i;
		/*2.2 执行SQL语句*/
		r = sqlite3_step(pStmt);
		if (r == SQLITE_DONE)
		{
			printf("o la\n");
			break;//执行完成
		}
		else if (r == SQLITE_ROW) //获取到一行的结果
		{
			int cNum =0 ;//结果集中有多少列
			cNum = sqlite3_column_count(pStmt);
			if (first)
			{
				for (i = 0; i < cNum; i++)
				{	
					//返回结果集中第i列的名字
					const char *p = sqlite3_column_name(pStmt, i);
					printf("%s\t", p);
				}
				printf("\n---------------------------\n");
				first = 0;
			}
			int iType; //第i列的数据类型
			for (i = 0; i < cNum; i++)
			{
				//获取结果集中第i列的数据类型
				iType = sqlite3_column_type(pStmt, i);
				if (iType == SQLITE_INTEGER)
				{
					int iValue;
					//获取结果集中第i列的数据值
					iValue = sqlite3_column_int(pStmt, i);
					printf("%d\t", iValue);
				}else if (iType == SQLITE_FLOAT)
				{
					double iValue;
					//获取结果集中第i列的数据值
					iValue = sqlite3_column_double(pStmt, i);
					printf("%g\t", iValue);

					
				}else if (iType == SQLITE_TEXT)
				{
					const char * iValue;
					//获取结果集中第i列的数据值
					iValue = sqlite3_column_text(pStmt, i);
					printf("%s\t", iValue);
				}
			}
			printf("\n");
		}
	}
	//销毁一个SQL语句对象
	sqlite3_finalize(pStmt);
	
	/*step 3: 关闭数据库连接对象*/
	sqlite3_close(pdb);
	return 0;
}

使用示例二(sqlite3_get_table 方式获取执行结果):

#include <sqlite3.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

#define  TABLE_NAME  xxx  //表名
#define  CARD_ID  xxx //卡ID
#define  TYPE  xxx //类型
int main(int argc, char *argv[])
{
	sqlite3 *pdb;
	int rc = 0; //返回值
    int nrow = 0;       //查询到数据的行数
    int ncolumn = 0;   //查询到数据的列数
    char **azResult;   //二维数组存放结果
    char sql[128]={0};   //sql语句
    char *zErrMsg = NULL; //错误信息

	/*step 1: 打开数据库连接对象*/
	rc = sqlite3_open(argv[1], &pdb );
	if (r != SQLITE_OK)
	{
		perror("sqlite3_open error");
		return -1;
	}

	/*step 2: sql语句对象。*/
	sqlite3_stmt *pStmt;
	sprintf(sql,"SELECT * FROM %s WHERE cardId = '%s' AND type = %d;", TABLE_NAME, CARD_ID, TYPE );
	
	rc = sqlite3_prepare_v2(
				pdb, //数据库连接对象
				sql, //指向原始sql语句字符串
				strlen(sql) , //
				&pStmt,
				NULL
			);
	if (rc != SQLITE_OK)
	{
		perror("sqlite3_prepare_v2 error:");
		return -1;
	}

    printf("The SQL CMD:%s\n",sql);
	
    rc = sqlite3_get_table( pdb, sql, &azResult, &nrow, &ncolumn, &zErrMsg ); //查询数据库
    if( rc != SQLITE_OK )
    {
        fprintf(stderr,"Can't get table: %s",sqlite3_errmsg(pdb));
        return -1;
    }

    printf( "nrow = %d ,ncolumn = %d\n", nrow, ncolumn ); //打印查询结果表的行数和列数
    if( nrow !=0 && ncolumn != 0 )     //有查询结果,不包含表头所占行数
    {
        int i=0,j=0;
        for(i=0; i<= nrow; i++)           //打印查询结果
        {
             for(j=0; j<ncolumn; j++)
             {
                  if(i==0) //第0行为数据表头
                  {
                     printf("%s\t", azResult[i+j]);
                  }
                  else
                     printf("%s\t", azResult[i+j]);
             }
             printf("\n");
        }
        
    }
	sqlite3_free_table(azResult);     //释放掉 azResult的内存空间
	
	sqlite3_finalize(pStmt);     //销毁一个SQL语句对象

	/*step 3: 关闭数据库连接对象*/
	sqlite3_close(pdb);

	return 0;
}   

二、sqlite3回调形式接口用法

一步到位的函数接口: sqlite3_exec

sqlite3_exec其实是sqlite3_prepare_v2、sqlite3_step、sqlite3_finalize 三个函数的组合。

函数原型及用法:

int sqlite3_exec( sqlite3* , //指向数据库连接对象
                  const char *sql , //指向要执行的SQL语句,一般不带参数。
                  int (*callback) (void *, int, char **, char **), //回调函数
                  void *arg, //这个函数将作为callback的第一个参数传入
                  char **errmsg //用来保存出错的信息        
                );
第一个参数,数据库连接对象

第二个参数,要执行的sql语句,可以执行多条语句以;分开

第三个参数,函数指针,回调函数。一般在sql语句为select语句时,需要回调。每查询到一条结果时(一行),就调用该回调函数。
int (*callback)(
                  void *,     //sqlite3_exec的第四个参数
                  int,    //结果中有多少列 
                  char **, // char *column_values[],这一行每列的值(转化成字符串)
                  char **  //char *column_names[],这一行每列的名字(字符串)
           ), 
回调函数的返回值: 返回0表示成功,其他值表示失败,回调函数执行失败了(返回非0值),sqlite3_exec就不执行下面的语句了。

第四个参数:将作为回调函数的第一个参数.

第五个参数: *errmsg将保存执行过程中的错误信息。

返回值:  成功返回0, 失败返回其他值。

使用示例:

#include <sqlite3.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

int select_cb(void *data, int cNum, char *column_values[], char *column_names[]) //回调函数,处理sql语句执行结果
{
	int *p = (int *)data;
	int i;
	if ( *p )
	{
		for (i = 0; i < cNum; i++)
		{
			printf("%s\t", column_names[i]);
		}
		printf("\n");
		*p = 0;
	}
	for (i = 0; i < cNum; i++)
	{
		printf("%s\t",column_values[i]);
	}
	printf("\n");
	return 0;
}

int main(int argc, char *argv[])
{
	sqlite3 *pdb;
	int r ;
	/*step 1: 打开数据库连接对象*/
	r = sqlite3_open(argv[1], &pdb );
	if (r != SQLITE_OK)
	{
		perror("sqlite3_open error");
		return -1;
	}

    /* sql语句 */
	char *sql=	"SELECT STUINFO.SID,SNAME,CNAME,SCORE\
					FROM STUINFO, COURCE, SCORE\
					WHERE STUINFO.SID = SCORE.SID \
					AND COURCE.CID = SCORE.CID ;";

	int first = 1;
    
    /*step 2: 执行sql语句*/
	r = sqlite3_exec(pdb,sql,select_cb,(void*)&first,NULL);
	
    /*step 3: 关闭数据库连接对象*/
	sqlite3_close(pdb);
     
    return 0;
}

回调形式接口详细可参考: http://www.runoob.com/sqlite/sqlite-c-cpp.html

猜你喜欢

转载自blog.csdn.net/fangye945a/article/details/86484547
今日推荐