snifer

【原创】基于嵌入式系统的SQLite C/C++接口

0
阅读(3089)

由于早期的SQLite 只支持5 个C/C++接口,因而非常容易学习和使用,但是随着SQLite 功能的增强,新

的C/C++接口不断的增加进来,到现在有超过150 个不同的API 接口。这往往使初学者望而却步。幸运的是,

大多数SQLite 中的C/C++接口是专用的,因而很少被使用到。尽管有这么多的调用接口,核心的API 仍然相

对简单和便于调用。

以下举例常用的SQLite 数据库与用户应用程序C/C++接口

 sqlite3_open()

该接口打开与一个SQLite 数据库文件的连接并返回一个数据库连接对象。这通常是应用程序调用的第一

个SQLite API 接口而且也是调用其他SQLite API 接口前需要调用的接口。许多SQLite 接口需要一个指向数

据库连接对象的指针作为它们的第一个参数,因而这些接口也可以理解成是数据库连接对象的操作接口。该

接口就是创建了这样一个数据库连接对象。

sqlite3_prepare()

该接口把一个SQL 语句文本转换成一个预处理语句对象并返回一个指向该对象的指针。这个接口需要一

个由先前调用sqlite3_open()返回的数据库连接对象指针以及一个预处理的SQL 语句文本字符串为参数。这

个API 并不实际解析SQL 语句,仅仅是为后续的解析而对SQL 语句进行的预处理。

􀁺 sqlite3_step()

该接口用于解析一个由先前通过sqlite3_prepare()接口创建的预处理语句,直至返回第一列结果为止。

通过再次调用sqlite3_step()可以返回下一列的结果,继续不断地调用sqlite3_step()直至整个语句完成为

止。对于那些并不返回结果的语句(例如:INSERT,UPDATE,DELETE 语句)一次调用sqlite3_step()就完成了

语句的处理。

sqlite3_column()

该接口返回一个由sqlite3_step()解析的预处理语句结果集中当前行的某一列数据。每次执行

sqlite3_step()都返回一个新的结果集中的一行。可以多次调用sqlite3_column()接口返回那一行中所有列

的数据。就像上面所说的那样,SQLite API 中并没有sqlite3_column()这样的接口。取而代之的是一组用于

从结果集中查询出各个列项各种数据类型数据的函数接口。在这组函数接口中,有些接口返回结果集的大小,

有些返回结果集的列数。

-- sqlite3_column_blob()

-- sqlite3_column_bytes()

-- sqlite3_column_bytes16()

-- sqlite3_column_count()

-- sqlite3_column_double()

-- sqlite3_column_int()

-- sqlite3_column_int64()

-- sqlite3_column_text()

-- sqlite3_column_text16()

-- sqlite3_column_type()

-- sqlite3_column_value()

sqlite3_finalize()

该接口销毁之前调用sqlite3_prepare()创建的预处理语句。每一个预处理语句都必须调用这个接口进行

销毁以避免内存泄漏。

sqlite3_close()

该接口关闭一个由之前调用sqlite3_open()创建的数据库连接。所有与该连接相关的预处理语句都必须

在关闭连接之前销毁。

一个应用程序可以通过执行以下几个步骤执行一条SQL 语句:

(1) 使用sqlite3_prepare()创建一个预处理语句。

(2) 重复调用sqlite3_step()解析执行预处理语句。

(3) 对于查询操作,两次调用sqlite3_step()之间通过sqlite3_column()接口查询返回的结果。

(4) 最后,使用sqlite3_finalize()销毁预处理语句。

上述就是有效使用SQLite 所需要知道的知识,其余的仅仅是些需要补充的细节而已。

sqlite3_exec()

该接口是执行上述四个步骤的一个方便的应用调用封装接口,传递给sqlite3_exec()的回调函数用于处

理每一列返回的结果集。

关键代码分析

1、consoleshell.c 源码分析

consoleshell.c 源文件主要是建立用户终端显示控制台菜单,并根据用户的输入字符,调用相应的接口

函数。

#include "consoleshell.h"

char shell_s[]="\nshell> ";

void get_line(char *cmd);

/**

**

**控制台

**

*/

void * consoleshell(){

int count=0;

int i;

char cmd[256]={0,};

int rc = sqliteDB_open();

char name[40],id[40];

int price = 0;

/* 打印终端控制台菜单 */

printf("\n<DB control shell>");

printf("\n [1] select all the records in table merchandise");

printf("\n [2] select the the record which you known its name");

printf("\n [3] select the record by the id");

printf("\n [4] delete record");

printf("\n [5] add record");

printf("\n [**] help menu");

printf("\n [0] print the end of the context an exit");

while(1){

printf(shell_s);

fflush(stdout);

/* 获取用户终端输入 */

get_line(cmd);

/* 根据输入批处理SQLite 接口调用 */

if(strncmp("1",cmd,1)==0){

/* 选择全部商品记录 */

sqliteDB_opt_select_all();

}else if(strncmp("2",cmd,1)==0){

/* 根据名字查找商品记录 */

printf("\nenter the record name ");

printf("\nname:");

scanf("%s",name);

fflush(stdin);//刷新缓冲区

if(!sqliteDB_exist(name))

continue;

sqliteDB_opt_select(name);

}else if(strncmp("3",cmd,1)==0){

/* 根据ID 查找商品记录 */

printf("\nenter the record id ");

printf("\nid:");

scanf("%s",id);

fflush(stdin);//刷新缓冲区

sqliteDB_opt_select_by_id(id);

}else if(strncmp("4",cmd,1)==0){

/* 根据名字删除商品记录 */

printf("\nplease enter the info of the record you want to

delete!");

printf("\nname:");

scanf("%s",name);

fflush(stdin);//刷新缓冲区

if(!sqliteDB_exist(name))

continue;

sqliteDB_opt_select(name);

//删除之前应再次询问是否删除,不可回滚

sqliteDB_opt_delete(name);

}else if(strncmp("5",cmd,1)==0){

/* 增加商品记录 */

printf("\nplease enter the info of the record you want to

add!\nid:");

printf("\nenter the record id ");

printf("\nid:");

scanf("%s",id);

printf("\nname:");

scanf("%s",name);

fflush(stdin);//刷新缓冲区

printf("\nprice:");

scanf("%d",&price);

fflush(stdin);//刷新缓冲区

sqliteDB_opt_add(name,id,price);

}else if(strncmp("**",cmd,2)==0){

/* 显示帮助控制台菜单 */

printf("\n<DB control shell>");

printf("\n [1] select all the records in table

merchandise");

printf("\n [2] select the the record which you known its

name");

printf("\n [3] select the record by the BarCode Scanner");

printf("\n [4] delete record");

printf("\n [5] add record");

printf("\n [**] help menu");

printf("\n [0] print the end of the context an exit");

}else if(strncmp("0",cmd,1)==0){

/* 退出 关闭数据库 */

sqliteDB_close();//关闭数据库连接

break;

// }else if(cmd[0] != "0"){

}else if(strncmp("0",cmd,1)!=0){

system(cmd);

}

}

}

/* 获取用户终端输入 */

void get_line(char *cmd){

int i=0;

while(1){

cmd[i]=getchar();

if(cmd[i]==10){

cmd[i]=0;

break;

}

fflush(stdout);

i++;

}

}

2、SQLite.c 源程序分析

该源码文件主要是对SQLite 数据的C/C++接口封装,提供consoleshell.c 中程序调用。

/*

*建立与数据库的连接

*/

int sqliteDB_open(){

int rc;//操作标志

printf("\ncreat database:test.db\n\ncreat table:table

merchandise(contents:id name price)\n\nand add two records\n");

rc = sqlite3_open("test.db", &db);

if( rc ){

fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));

sqlite3_close(db);

exit(1);

}

printf("\nOpen sucess!");

/* 建立商品初始化table */

if(!sqliteDB_create_table())

printf("\ntable exist");

return 1;

}

/*

* 关闭与数据库的连接

*/

int sqliteDB_close(){

if(db != 0)

sqlite3_close(db);

}

/*

* 添加一条记录到已知或未知数据库表

*/

int sqliteDB_opt_add(char *name,char *id,int price){

int rc;

char *zErrMsg = 0;

char *sql=0;//动态生成的SQL 语句

/* 定义SQL 语句格式字符串 */

char tem_sql[256]="insert into merchandise values('";

char tem_sql0[5] = "','";

char tem_sql1[5] = "',";

char tem_sql2[5] = ");";

char tem_price[20];

sprintf(tem_price, " %d" , price);//将int 数据转换为字符串

/* 组合SQL 语句格式 */

sql = strcat(tem_sql,name);

sql = strcat(sql,tem_sql0);

sql = strcat(sql,id);

sql = strcat(sql,tem_sql1);

sql = strcat(sql,tem_price);

sql = strcat(sql,tem_sql2);

/* 添加记录到SQLite */

rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);

if( rc!=SQLITE_OK ){

fprintf(stderr, "SQL error: %s\n", zErrMsg);

sqlite3_free(zErrMsg);

以上由于篇幅有限,给出部分代码,其他接口原理相同,大家可以自行分析该文件全部源码。