写点什么

C++ sqlite3 使用指南

发布于: 2020 年 05 月 09 日
C++ sqlite3使用指南

我在客户端开发时由于需要使用数据库,于是选择了轻巧的 sqlite 数据库研究了一下,今天在这里和大家分享下我总结的 sqlite 使用文档。

源码下载

wget http://www.sqlite.org/2017/sqlite-autoconf-3160200.tar.gztar xvzf sqlite-autoconf-3160200.tar.gz
复制代码

交叉编译

./configure --host=arm-himix200-linux --prefix=/home/zjucad/wangzhiqiang/toolDir/sqlite-autoconf-3160200/libsmakemake install
复制代码

按顺序执行上述命令后 sqlite 的链接库和头文件等就会出现在 prefix 目录下

api 使用

基本的使用流程

sqlite3_open()->sqlite3_prepare_v2()->sqlite3_step()->sqlite3_column()->sqlite3_finalize()->sqlite3_close()
复制代码

具体介绍:

int sqlite3_open(  const char *filename,   /* Database filename (UTF-8) */  sqlite3 **ppDb          /* OUT: SQLite db handle */);打开一个数据库,第一个参数为数据库的路径,注意这里不能为:memory:,这表示存在内存中,第二个参数为返回,返回这个数据库的handle,函数返回值是int,成功则返回SQLITE_OK,失败的话可以通过sqlite3_errmsg()查看错误信息。注:sqlite还有个sqlite3_open_v2()函数,添加一些flag,看着不太常用。
复制代码


int sqlite3_prepare_v2(  sqlite3 *db,            /* Database handle */  const char *zSql,       /* SQL statement, UTF-8 encoded */  int nByte,              /* Maximum length of zSql in bytes. */  sqlite3_stmt **ppStmt,  /* OUT: Statement handle */  const char **pzTail     /* OUT: Pointer to unused portion of zSql */);准备数据库语句的上下文,相当于编译sql语句,最后由step函数执行编译好的语句,ppStmt需要自己首先定义好,最后一个参数基本传NULL。注:sqlite还有个sqlite3_prepare()函数,但是现在官方推荐使用v2版本,有错误v2版本能够立即暴露出来。
复制代码

一般使用 sqlite3_prepare_v2()都是和 sqlite3_bind_xxx()系列函数一起使用,例如执行插入语句,使用 sqlite3_bind_xxx()可以动态绑定某些参数的值,后续给出示例代码。

int sqlite3_step(sqlite3_stmt*);执行数据库语句
复制代码


int sqlite3_reset(sqlite3_stmt *pStmt);重置数据库上下文,当需要重新bind参数时可以使用这个函数,避免多次prepare。
复制代码


int sqlite3_finalize(sqlite3_stmt *pStmt);删除数据库语句的上下文,调用了sqlite3_prepare_v2()后无论成功失败都需要调用,避免内存泄漏。
复制代码


int sqlite3_close(sqlite3 *);关闭数据库
复制代码

在执行查询操作时,可能结果不止一条,那 sqlite3_step()函数就会返回 SQLITE_ROW 直到所有结果都被查询到会返回 SQLITE_DONE,这里每次 sqlite3_step()返回 SQLITE_ROW 后都需要再次调用返回下一次查询的结果。

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);double sqlite3_column_double(sqlite3_stmt*, int iCol);int sqlite3_column_int(sqlite3_stmt*, int iCol);sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);int sqlite3_column_type(sqlite3_stmt*, int iCol);sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
执行查询语句后需要使用这类函数,获取查询到的结果,第二个参数代表第几列,需要根据数据库表的每一列具体类型调用相应的函数,可以通过sqlite3_column_type()获取某一列的类型,通过sqlite3_column_count()函数获取这次查询结果共有多少列。
复制代码

在一些简单的场景下也可以使用 sqlite3 的 wrapper 函数

主要有 sqlite3_exec()和 sqlite3_get_table()函数,相当于调用了 sqlite3_prepare_v2()->sqlite3_step()->sqlite3_finalize()这个流程。


区别是 sqlite3_exec()在查询中需要添加回调函数,sqlite3_get_table()主要用在查询上,没有回调,会把查询到的结果存到一块地址。

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 */);
注意这里的最后一个参数是错误信息,如果执行函数没有返回SQLITE_OK,可以查看errmsg处的信息,这块内存也需要自己手动调用sqlite3_free()来释放。
复制代码


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 */);void sqlite3_free_table(char **result);
sqlite3_get_table()主要用在查询上,会把查询到的结果存到一块地址。由调用者手动调用sqlite3_free_table()释放内存。
复制代码

注意事项

  • sqlite3-column-text()等函数返回的地址不需要自己 free,sqlite 会在调用 sqlite3_step() or sqlite3_reset() or sqlite3_finalize()时自动释放


  • 如何设置自增字段

字段是 integer 的 primary key 就会自增

CREATE TABLE t1(a INTEGER PRIMARY KEY,b INTEGER);
复制代码

如上代码,字段 a 就会自增,最大值是 9223372036854775807,如果 insert 超过了这个数量,就会返回 SQLITE_FULL 错误,但 90%的数据库行数可能不会超过这个数量。

示例代码

sqlite3 *db_;std::string sql =        "create table if not exists sqlite("        "id INTEGER primary key     AUTOINCREMENT,"        "value      int64      not null);";char *err_msg = NULL;int ret = sqlite3_exec(db_, sql.c_str(), NULL, 0, &err_msg);if (ret != SQLITE_OK) {    std::cout << "create table error " << err_msg;    sqlite3_free(err_msg);    return false;}
复制代码


std::string sql =        "insert into sqlite(value) values(?1)";sqlite3_stmt *stmt;int ret = sqlite3_prepare_v2(db_, sql.c_str(), -1, &stmt, NULL);if (ret != SQLITE_OK) {    std::cout << "prepare sql error " << ret << " " << sqlite3_errcode(db_);    return false;}if (sqlite3_bind_int64(stmt, 1, 1) != SQLITE_OK) {    std::cout << "bind timestamp error " << sqlite3_errcode(db_);    return false;}if (sqlite3_step(stmt) != SQLITE_DONE) {    std::cout << "step insert fail " << sqlite3_errcode(db_);    return false;}sqlite3_finalize(stmt);
复制代码

有问题,欢迎私信或留言,我每天都会上线~


发布于: 2020 年 05 月 09 日阅读数: 158
用户头像

安身立命 (公众号:程序喵大人) 2018.05.26 加入

公众号:程序喵大人

评论

发布
暂无评论
C++ sqlite3使用指南