Sqlite使用笔记

| 2014年4月10日

在目前做的元数据节点中,为了保存一些节点的私有数据,选择了本地存储,在选择本地存储的选择上又选择了使用sqlite,sqlite对数据存储和数据解析在使用比较简单。而且编译入当前代码也是比较容易的。

Sqlite常使用的函数有下面几个。

sqlite3_open()
sqlite3_errcode(_sqlite) 
sqlite3_errmsg()
sqlite3_get_table()
sqlite3_exec()
sqlite3_prepare()
sqlite3_step()
sqlite3_column()
sqlite3_finalize()
sqlite3_close()

sqlite3_open的接口定义如下:

int sqlite3_open(
  const char *filename,   /* Database filename (UTF-8) */
  sqlite3 **ppDb          /* OUT: SQLite db handle */
);

直接传入db文件的路径,和sqlite空对象指针,如果打开成功,sqlite则指向打开的sqlite对象,打开失败则指向NULL,打开成功返回值为SQLITE_OK,如果不为SQLITE_OK则可以调用函数sqlite3_errcode(_sqlite) 和sqlite3_errmsg()来获取打开失败原因。如下:

 if (sqlite3_open(_db_name.c_str(), &_sqlite) != SQLITE_OK)                                      
    {                                                                                               
        int errcode = sqlite3_errcode(_sqlite);                                                     
        LOG(ERROR) << "opened " << _db_name << " ERROR("                                            
            << errcode << "): " << sqlite3_errmsg(_sqlite);                                         
                                                                                                    
        return false;                                                                               
    } 

关闭sqlite函数是sqlite3_close(),定义如下:

int sqlite3_close(sqlite3*);
  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 */
);

zSql可以是多条sql语句,返回的结果放在pazResult中,以数组方式存放,官方文档的例子说明:

Name        | Age
-----------------------
Alice       | 43
Bob         | 28
Cindy       | 21
azResult[0] = "Name";
azResult[1] = "Age";
azResult[2] = "Alice";
azResult[3] = "43";
azResult[4] = "Bob";
azResult[5] = "28";
azResult[6] = "Cindy";
azResult[7] = "21";

这些内存都是在sqlite3_get_table内部查询时申请的,因此为了避免内存泄漏,使用完了之后需要释放掉,释放这样的内存函数:sqlite3_free_table,定义如下:

void sqlite3_free_table(char **result);

如果查询失败则在最后一个参数pzErrmsg中赋值错误原因,查询成功该值是NULL,当然这个字符串的内存也是在sqlite3_get_table内部申请的,释放这部分内存要是用sqlite3_free()函数,直接调用即可:

  sqlite3_free(pzErrmsg);
 std::string check_sql = boost::str(boost::format("select * from %s limit 1;") % tbname);        
    int ret = sqlite3_get_table(_sqlite, check_sql.c_str(), &result,                                
                                &num_rows, &num_cols, &errmsg);                                     
    if (ret != SQLITE_OK)                                                                           
    {                                                                                               
        LOG(ERROR) << check_sql << " sqlite db:" << _sqlite << " ERROR: " << errmsg;                
        sqlite3_free(errmsg);                                                                       
    }                                                                                               
    sqlite3_free_table(result);                                                                     
                                                                                                    
    return (SQLITE_OK == ret);  

int ret = sqlite3_get_table(sqlite, sql.c_str(), &table, &num_rows, &num_cols, &errmsg);        
    if (ret != SQLITE_OK)                                                                           
    {                                                                                               
        LOG(ERROR) << "sqlite sql[" << sql << "] ERROR: " << errmsg;                                
        sqlite3_free(errmsg);                                                                       
        return false;                                                                               
    }                                                                                               
    else                                                                                            
    {                                                                                               
        bool is_error = false;                                                                      
        for (int i=0; i<num_rows; ++i)                                                              
        {                                                                                           
            int field_no = 0;                                                                       
            int index = (i + 1) * num_cols;                                                         
                                                                                                    
            char* total_file_num = table[index + field_no++];                                       
            char* total_file_size = table[index + field_no++];                                      
                                                                                                    
            try                                                                                     
            {                                                                                       
                _total_file_num = boost::lexical_cast<uint32_t>(total_file_num);                    
                _total_file_size = boost::lexical_cast<uint64_t>(total_file_size);                  
            }                                                                                       
            catch (boost::bad_lexical_cast& ex)     
。。。。。                               

sqlite3_exec()是也是用来执行sql语句:   一般用作更新操作,比如删除,更新,插入等sql的执行,调用起来也比较简单,这个函数是sqlite3_prepare_v2(), sqlite3_step(), and sqlite3_finalize()这几个函数的封装,一次性调用执行了上面几个函数。当然也可以用来做查询任务,使用其参数callback函数进行查询结果的处理。接口定义如下:

  int sqlite3_exec(
    sqlite3*,                          /* An open database */
    const char *sql,                    /* SQL to be evaluated */
    int (*callback)(void*,int,char**,char**), /* Callback function */
    void *,                            /* 1st argument to callback */
    char **errmsg                      /* Error msg written here */
  );

我在使用中一般使用该函数进行增删改sql。

bool CSqliteHelp::update(const std::string& sql)                                                    
{                                                                                                   
    char* errmsg = NULL;                                                                            
    int ret = sqlite3_exec(_sqlite, sql.c_str(), 0, 0, &errmsg);                                    
    if (ret != SQLITE_OK)                                                                           
    {                                                                                               
        LOG(ERROR) << sql << " ERROR: " << errmsg;                                                  
        sqlite3_free(errmsg);                                                                       
        return false;                                                                               
    }                                                                                               
                                                                                                    
    return true;                                                                                    
}
``` 
sqlite3_prepare()也是一个执行查询sql的函数,查询结果在后面的代码可以使用sqlite3_step() 逐条取出使用,每次取结果集中的一行。
```c
nret = sqlite3_prepare(_sqlite, sql.c_str(), sql.size(), &stmt_tmp, &errmsg);                   
    if(SQLITE_OK == nret)                                                                           
    {                                                                                               
        *stmt = stmt_tmp;                                                                           
    }                                                                                               
    else                                                                                            
    {                                                                                               
        LOG(ERROR) << sql << " ERROR: " << errmsg;                                                  
        sqlite3_finalize(stmt_tmp);                                                                 
  } 
  ........
  while (sqlite3_step(stmt) == SQLITE_ROW)                                                        
    {                                                                                               
        bool ret = true;                                                                            
        uint64_t md5 = 0;                                                                           
        uint64_t size = 0;                                                                          
        std::string path = (const char*)sqlite3_column_text(stmt, 0);  
.......
  }
    sqlite3_finalize(stmt);  

  
取其中字段的函数如下,这些都是取对应的类型的函数,直接使用即可。

  sqlite3_column_double
  sqlite3_column_int
  sqlite3_column_int64
  sqlite3_column_blob
  sqlite3_column_bytes
  sqlite3_column_bytes16
  sqlite3_column_text
    sqlite3_column_text16

  sqlite3_prepare使用的查询结果内存也是在内部申请的,在使用完之后就需要释放,释放使用sqlite3_finalize()函数:    跟多相关函数可以在这里查看:    http://www.sqlite.org/c3ref/funclist.html

看完本文有收获?请分享给更多人

关注「黑光技术」,关注大数据+微服务