分类目录归档:数据库

记录一个C/C++使用使用sqlite3的小坑

运行查询指令的时候,无法查询到信息,是不会进入回调函数的,可以利用这个点判断数据库里面是否有查询的记录。

 

技术细节稍后更新

—————————-2018.9.8更新————————————

        首先回调函数一般是指,自己定义一个函数的功能,然后把函数作为参数传入另一个函数里面,在另一个函数里面会执行我们自己定义的函数,这个我们定义的函数叫回调函数。回调函数的参数需要符合另一个函数的要求,才能被传入、调用。而这另一个函数一般是我们无法直接更改内容的一个黑盒,但是我们可以通过自己定义的回调函数来操控程序。

        c/c++的sqlite库中执行SQL命令的函数sqlite3_exec原型如下:

sqlite3_exec(sqlite3* pdb, const char *sql, sqlite_callback func, void *data, char **errmsg);

sqlite3* pdb是指向已经打开的数据库的指针;

const char * sql是需要执行的sql语句,注意在c++中如果是string的话需要传参的时候用c_str()更改一下类型;

sqlite_callback func是一个回调函数,如果不需要回调,可以传实参为NULL,使用select语句时,每产生一条记录都会调用一次回调函数;

void *data将会作为参数传入回调函数,作为回调函数的第一个参数,利用这点可以向回调函数中动态传入数据;

char errmsg保存执行命令时发生的错误,注意errmsg是char类型的,但是错误语句应该是char类型的,那么我们传入实参的时候就一个调用&取一个char类型的变量,这样就好了,sqlite3_exec执行完毕之后错误会保存在这个变量指向的字符串里面;


回调函数:

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

void*是exec里面的第四个参数,int是记录的列数,第一个char是一个二维数组,记录查到的值,第二个char保存键名


 

         当使用sqlite3_exe执行select语句时,如果没有查询到记录,是不会报错的,那么怎么知道没有查到记录呢?

如果查到了相关记录,会调用回调函数,查询到的记录条数是0的话,就不会调用,可以利用sqlite3_exec的第四个void *参数,向回调函数里面传入一个变量,在回调函数中改变这个变量的值,在exec执行完毕之后判断变量的值是否被改变,这样就可以知道是否查询到了值。这样可以避免某些错误。

        例如我在某个程序中写的代码:

static int callback_sqlite(void * data,int argc,char **argv,char **azColName){
    int i=0;
    #ifdef _DEBUG_
    printf("进入回调函数\n");
    #endif
    string keys[]={"word","phonetic","pos","acceptation","orig","trans"};
    for(i=0;i<argc;i++){
        #ifdef _DEBUG_
        printf("内存地址:%p\n",argv);
        printf("数据库查询中:%s\n",argv[i]);
        #endif
        (*(map<string,string>*)data).insert(pair<string,string>(keys[i],argv[i]?string(argv[i]):string("NULL")));
    }
    #ifdef _DEBUG_
    printf("退出回调函数\n");
    #endif
    (*(map<string,string>*)data)["isExistWord"]="true";
    return 0;
}

Interpretation inquire_core(sqlite3 * db,string word){
    Interpretation tempTransDataObj;
    char *ErrorInfo=0;
    int rc;
    map<string,string> WordData;
    WordData.insert(pair<string,string>("isExistWord","false"));
    string sql_cmd="select word,ps,pos,acceptation,orig,trans from words where word=\'";
    sql_cmd=sql_cmd+word+"\';";
    rc=sqlite3_exec(db,sql_cmd.c_str(),callback_sqlite,(void *)&WordData,&ErrorInfo);
    if(rc!=SQLITE_OK){
        cout<<"SQL ERROR:"<<ErrorInfo<<endl;
        sqlite3_free(ErrorInfo);
        exit(0);
    }else{
        #ifdef _DEBUG_
        cout<<"查询数据库成功"<<endl;
        #endif
    }
    sqlite3_close(db);
    map<string,string>::iterator it;
    it=WordData.find(string("isExistWord"));
    if(it->second!="true"){
        return tempTransDataObj;
    }
……
……
……
}