概述
     SQLite提供了一系列接口供用户访问数据库,主要包括连接数据库,处理SQL,迭代查询结果等。本文会针对我们使用SQLite的主要场景,列出核心的API,详细介绍API的用法并给出代码用例。
1.打开关闭数据库
sqlite3_open_v2
原型:

  1. int sqlite3_open_v2(
  2. const char *filename, /* Database filename (UTF-8) */
  3. sqlite3 **ppDb, /* OUT: SQLite db handle */
  4. int flags, /* Flags */
  5. const char *zVfs /* Name of VFS module to use */
  6. );

作用:打开一个数据库连接
关键的参数:flags
SQLITE_OPEN_NOMUTEX: 设置数据库连接运行在多线程模式(没有指定单线程模式的情况下)
SQLITE_OPEN_FULLMUTEX:设置数据库连接运行在串行模式。
SQLITE_OPEN_SHAREDCACHE:设置运行在共享缓存模式。
SQLITE_OPEN_PRIVATECACHE:设置运行在非共享缓存模式。
SQLITE_OPEN_READWRITE:指定数据库连接可以读写。
SQLITE_OPEN_CREATE:如果数据库不存在,则创建。

sqlite3_close_v2
原型:

  1. int sqlite3_close_v2(sqlite3*);

作用:关闭数据库连接,若关闭时连接上有未提交的事务,该事务会自动回滚。

1.1 例子:打开关闭数据库连接

  1. sqlite3* pDb;
  2. char* filename="/u01/sqlite/test.db";
  3. sqlite3_open_v2(filename, &pDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_SHAREDCACHE, NULL);
  4. ....
  5. ....
  6. sqlite3_close_v2(pDb);

打开数据库文件test.db,对应的数据库连接可读可写,以多线程模式运行,并且运行在共享缓存模式,执行完操作后,关闭数据库连接。

2.更新SQL
更新SQL主要包括创建表,插入,删除,更新记录等,SQLite中常用的更新API有两个,一个是sqlite3_exec,另外一个是sqlite3_prepare_v2。

2.1 sqlite3_exec
原型:

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

其中参数sql可以包含多个SQL命令,语句之间以分号隔开,sqlite3_exec()将解析和执行sql字符串中的每个命令,直到到达该字符串的末尾或遇到错误。对于运行修改数据库的命令(创建,插入,删除,更新)非常适合,一个函数调用就可以完成全部操作。需要注意的是,虽然sqlite3_exec()可以执行多个SQL命令,但是函数不保证事务,即已执行成功的语句,不会因为后面执行失败的语句而回滚。

2.2 sqlite3_perpare_v2
原型:

  1. int sqlite3_prepare_v2(
  2. sqlite3 *db, /* Database handle */
  3. const char *zSql, /* SQL statement, UTF-8 encoded */
  4. int nByte, /* Maximum length of zSql in bytes. */
  5. sqlite3_stmt **ppStmt, /* OUT: Statement handle */
  6. const char **pzTail /* OUT: Pointer to unused portion of zSql */
  7. );

sqlite3_exec实际上是将编译,执行进行了封装,与之等价的一组函数是 sqlite3_prepare_v2(), sqlite3_step()和sqlite3_finalize()。sqlite3_prepare_v2()编译SQL语句生成VDBE执行码,sqlite3_step()执行,sqlite3_finalize()关闭语句句柄,释放资源。两种方式,都可以通过调用sqlite3_changes(pdb),得到语句影响的行数。

2.3两种方式比较
(1).sqlite3_exec方式接口使用很简单,实现同样的功能,比sqlite3_perpare_v2接口代码量少。
(2).sqlite3_prepare方式更高效,因为只需要编译一次,就可以重复执行N次。
(3).sqlite3_prepare方式支持参数化SQL。

鉴于两种方式的差异,对于简单的PRAGMA设置语句(PRAGMA cache_size=2000),事务设置语句(BEGIN TRANSACTION,COMMIT,ROLLBACK)使用sqlite3_exec方式,更简单;而对于批量的更新、查询语句,则使用sqlite3_prepare方式,更高效。

2.4 例子:prepare方式执行多sql的例子,pNext初始化在sql语句首部,执行完一个sql后,移动到下一个sql首部。

  1. const char *pNext = (const char *)sql;
  2. while (pNext && strlen(pNext) > ) {
  3.   rc = sqlite3_prepare_v2(pDb, pNext, -, &pStmt, &pNext);
  4.   if(SQLITE_OK != rc){
  5.     错误处理
  6.     break;
  7.   }

  8. rc = sqlite3_step(pStmt);
  9. if(SQLITE_OK != rc && SQLITE_DONE != rc){
  10.    错误处理
  11.    break;
  12. }

  13. rc = SQLITE_OK;
  14.  
  15. /*统计影响记录数目*/
  16. resultCount += sqlite3_changes(pDb);
  17.  
  18. /* 清理语句句柄,准备执行下一个语句*/
  19. sqlite3_finalize(pStmt);
  20. }

3.查询SQL
3.1 sqlite3_get_table
原型:

  1. int sqlite3_get_table(
  2. sqlite3 *db, /* An open database */
  3. const char *zSql, /* SQL to be evaluated */
  4. char ***pazResult, /* Results of the query */
  5. int *pnRow, /* Number of result rows written here */
  6. int *pnColumn, /* Number of result columns written here */
  7. char **pzErrmsg /* Error msg written here */
  8. );

该函数接收SQL语句返回的所有记录,使用sqlite内部分配的内存,将其存储在参数resultp中,必须使用sqlite3_free_table()释放内存。由于结果集可能非常大,会导致内存撑爆,因此对于大结果集的查询,不建议采用这种方式。

3.2 sqlite3_prepare_v2
     prepare方式同样支持查询语句,主要分为3个阶段,编译,执行和结果集处理。前面更新SQL部分已经描述了prepare的基本步骤,这里主要讲结果集处理部分。首先通过sqlite3_column_count()可以得到结果集的列数目,通过sqlite3_column_type()可以得到具体某列的存储类型,方便我们调用合适的sqlite3_column_xxx接口处理字段值。主要有以下几类:
sqlite3_column_int
sqlite3_column_int64
sqlite3_column_double
sqlite3_column_text
sqlite3_column_blob

3.3 例子:遍历结果集

  1. int rc = sqlite3_prepare_v2(pDb, sql, -, &pStmt, NULL);
  2. //获取列数目
  3. int n_columns = sqlite3_column_count(pStmt);
  4. do{
  5.   ret = sqlite3_step(stmt);
  6.   if (ret == SQLITE_ROW)
  7.   {
  8.     //处理每一列
  9.     for (i = ; i < n_columns; i++)
  10.     {
    /*获取列存储类型*/
  11.       type = sqlite3_column_type(stmt,i);
  12.       switch(type)
  13.       {
  14.         case SQLITE_INTEGER:
  15.          /*处理整型*/
  16.         sqlite3_column_int(stmt,i);
            break;
  17.         case SQLITE_FLOAT:
  18.         /*处理浮点数*/
  19.         sqlite3_column_double(stmt,i);
            break;
  20.         case SQLITE_TEXT:
  21.         /*处理字符串*/
  22.         sqlite3_column_text(stmt,i);
    break;
  23.         case SQLITE_BLOB:
  24.         /*处理二进制*/
  25.         sqlite3_column_blob(stmt, i));
            break;
  26.         case SQLITE_NULL:
  27.         /*处理空*/
  28.       }
  29.     }
  30.   }
  31.   else if (ret == SQLITE_DONE) //结束
  32.   {
  33.     break;
  34.   }
  35. }while(true);

4.参数绑定
     SQLite通过prepare接口可以支持参数化的SQL语句,即带问号的SQL语句。比如查询语句select * from t where id=?,或者插入语句 insert into t(a,b,c) values(?,?,?)。通过参数化SQL,可以实现一次编译多次执行的目的,由于问号是没有意义的,因此需要调用sqlite3_bind_xxx接口来绑定具体的参数。主要有以下几类:
sqlite3_bind_int
sqlite3_bind_int64
sqlite3_bind_double
sqlite3_bind_text
sqlite3_bind_blob
sqlite3_bind_null
关于绑定参数这里提一点,对于sqlite3_bind_text和sqlite3_bind_blob接口,绑定参数占据的存储空间是否可以被SQLite重用。接口中通过最后一个参数指定,参数值可以为SQLITE_STATIC和SQLITE_TRANSIENT。

SQLITE_STATIC:通知bind函数,参数使用空间是常量,不会改变,sqlite内部无需拷贝副本。
SQLITE_TRANSIENT:通知bind函数,参数使用空间可能会改变,sqlite内部需要有自己的副本。

4.1 例子:批量导入

  1. //begin a transaction
  2. if(sqlite3_exec(pdb, "begin", NULL, NULL, &errmsg) != SQLITE_OK)
  3. {
  4.   错误处理
  5.   return ERROR;
  6. }
  7.  
  8. sqlite3_prepare_v2(pdb, "insert into t1 values(?,?,?);", &stmt);
  9. for (i = ; i < n_rows; i++)
  10. {
  11.   for (j = ; j < n_columns; j++)
  12.   {
  13.     switch(type)
  14.     {
  15.       case SQLITE_INTEGER:
  16.       /*处理整型*/
  17.       sqlite3_bind_int()
          break;
  18.       case SQLITE_FLOAT:
  19.       /*处理浮点型*/
  20.       sqlite3_bind_double()
          break;
  21.       case SQLITE_TEXT:
  22.       /*处理字符串类型*/
  23.       sqlite3_bind_text()
          break;
          case SQLITE_BLOB:
  24.       /*处理二进制类型*/
  25.       sqlite3_bind_blob
          break;
  26.       case SQLITE_NULL:
  27.       sqlite3_bind_null(stmt, index);
          break;
  28.     }
  29.   }
  30.  
  31.   sqlite3_step(stmt); //执行
  32.   sqlite3_reset(stmt); //将已编译的SQL语句恢复到初始状态,保留语句相关的资源
  33. }
  34.  
  35. sqlite3_finalize(stmt); //结束语句,释放语句句柄
  36.  
  37. if(sqlite3_exec(pdb, "commit", NULL, NULL, &errmsg) != SQLITE_OK)
  38. {
  39.   错误处理   return ERROR;
  40. }

小结
     本文详细描述了SQLite中实现创建,修改,查询数据库的接口使用,包括单SQL语句,多SQL语句和参数化SQL。主要从四个场景展开描述,打开关闭数据库连接,更新语句,查询语句和参数化语句,并且对于每一种使用场景,给出了相应的代码示范,希望能对大家熟悉使用SQLite有所帮助。

SQLite使用(三)&&核心API使用的更多相关文章

  1. Spark2.0学习(三)--------核心API

    Spark核心API----------------- [SparkContext] 连接到spark集群,入口点. [HadoopRDD] 读取hadoop上的数据, [MapPartitionsR ...

  2. 支持GPS的核心API

    Android为GPS功能支持专门提供了一个LocationManager类,它的作用于TelephonyManager.AudioManager等服务类的作用相似,所有GPS定位相关的服务.对象都将 ...

  3. SDL 开发实战(二):SDL 2.0 核心 API 解析

    在上一篇文章 SDL 开发实战(一):SDL介绍及开发环境配置 中,我们配置好了SDL的开发环境,并成功运行了SDL的Hello World 代码.但是可能大部分人还是读不太明白具体Hello Wol ...

  4. 《Node.js高级编程》之Node 核心API基础

    Node 核心API基础 第三章 加载模块 第四章 应用缓冲区 第五章 事件发射器模式简化事件绑定 第六章 使用定时器制定函数执行计划 第三章 加载模块 本章提要 加载模块 创建模块 使用node_m ...

  5. Lucene系列六:Lucene搜索详解(Lucene搜索流程详解、搜索核心API详解、基本查询详解、QueryParser详解)

    一.搜索流程详解 1. 先看一下Lucene的架构图 由图可知搜索的过程如下: 用户输入搜索的关键字.对关键字进行分词.根据分词结果去索引库里面找到对应的文章id.根据文章id找到对应的文章 2. L ...

  6. Hibernate_day01--Hibernate配置文件详解_核心api

    Hibernate映射配置文件(重点) 1 映射配置文件名称和位置没有固定要求 2 映射配置文件中,标签name属性值写实体类相关内容 (1)class标签name属性值实体类全路径 (2)id标签和 ...

  7. Apache Spark 2.0三种API的传说:RDD、DataFrame和Dataset

    Apache Spark吸引广大社区开发者的一个重要原因是:Apache Spark提供极其简单.易用的APIs,支持跨多种语言(比如:Scala.Java.Python和R)来操作大数据. 本文主要 ...

  8. 配置文件详解和核心api讲解

    一.配置文件详解 1.映射文件详解 1.映射配置文件的位置和名称没有限制. -建议:位置:和实体类放在统一目录下.  名称:实体类名称.hbm.xml.    2.在映射配置文件中,标签内的name属 ...

  9. Vue.js 组件的三个 API:prop、event、slot

    组件的构成 一个再复杂的组件,都是由三部分组成的:prop.event.slot,它们构成了 Vue.js 组件的 API.如果你开发的是一个通用组件,那一定要事先设计好这三部分,因为组件一旦发布,后 ...

随机推荐

  1. C# 根据类型名称 生成实体 调用方法

    System.Reflection.Assembly ass = System.Reflection.Assembly.Load("项目名称或者DLL"); //System.Th ...

  2. 返回顶部的功能 div固定在页面位置不变

    1.你在网上搜索的时候,可能会搜索到div固定在页面上,不随滚动条滚动而滚动是用CSS写的,写法是position:fixed;bottom:0; 但是这个在iframe满地跑的页面实际开发中,有啥用 ...

  3. AFNetworking 3.0 源码解读(五)之 AFURLSessionManager

    本篇是AFNetworking 3.0 源码解读的第五篇了. AFNetworking 3.0 源码解读(一)之 AFNetworkReachabilityManager AFNetworking 3 ...

  4. position:sticky的兼容性尝试

    开篇 笔者刚刚结束淘宝的工作,现在加入了一家有青春活力的垂直电商公司,正对着阿里巴巴的西溪园区,最近一直在熟悉新的工作环境和规范,因此博客有好些时间没有更新了,在此抱歉! 在忙碌完公司的发布系统之后, ...

  5. Android GradientDrawable(shape标签定义) 静态使用和动态使用(圆角,渐变实现)

    Android GradientDrawable使用优势: 1. 快速实现一些基本图形(线,矩形,圆,椭圆,圆环) 2. 快速实现一些圆角,渐变,阴影等效果 3. 代替图片设置为View的背景 4. ...

  6. 1000行代码实现MVVM (类似Angular1.x.x , Vue)

    最近花了近半个多月的时间, 自己纯手工写了一个很小型的类angularjs/vue的mvvm 库. 目前已经用于公司一个项目. 项目托管在github https://github.com/leonw ...

  7. AngularJs学习笔记(制作留言板)

    原文地址:http://www.jmingzi.cn/?post=13 初学Anjularjs两天了,一边学一边写的留言板,只有一级回复嵌套.演示地址 这里总结一下学习的过程和笔记.另外,看看这篇文章 ...

  8. UML类图几种关系的总结

    在UML类图中,常见的有以下几种关系: 泛化(Generalization),  实现(Realization),关联(Association),聚合(Aggregation),组合(Composit ...

  9. 绑定一个值给radio

    在ASP.NET MVC程序中,需要给一个radio list表绑定一个值. 下面是Insus.NET实现的方法: 使用foreach来循环radio每一个选项,如果值与选项的值相同,那这个选项为选中 ...

  10. 使用PD(PowerDesigner)图如何快速生成创建数据库表的SQL脚本

    打开PD软件: 1.新建概念模型(conceptual Data Model) File-->New Model-->Conceptual Data Mode 或者点击工作区,右键--&g ...