SQLite学习心得
SQLite是一款很有名气的小型开源跨平台数据库,作为目前最流行的开源嵌入式关系型数据库,在系统结构设计中正在扮演着越来越重要的角色。
本文主要沿着 http://www.cppblog.com/weiym/archive/2012/10/16/193357.html 这篇文章里面的学习指导思想,来一步步学习SQLite,为的是快速在实际开发中利用好SQLite。
1. SQLite的优缺点以及适用场合
1. 1 优点
轻量级: 与传统的C/S模式的数据库软件不同,它是进程内的数据库引擎,不存在客户端和服务器。使用SQLite,只需要带上一个几百K大小的动态库就可以:
绿色组件: SQLite的核心引擎本身不依赖第三方软件,即插即用。
单一文件: 数据库中所有的信息(比如表、视图、触发器等)都保存在单个文件内,可以拷贝到其他地方,照用不误。
跨平台 : 不仅仅支持主流操作系统(Windows/Linux),还支持很多小型嵌入式系统(Android,WP,Vxworks)。
查询效率极高 : SQLite的API不区分当前数据库是保存在内存中还是在磁盘文件中,为了提高效率,可以切换为内存方式。只需要在开始时将数据库载入内存,读写完成后,再把内存数据库dump会磁盘文件上就可以,读写内存比读写磁盘快很多倍。
1.2 缺点
并发访问的锁机制: SQLite在并发读写方面的性能一直不太理想,在有大量insert,update访问时,不建议使用。
SQL标准支持不全 :
1.3适用场合
适合查询速度要求较高,内存占用较少的场合,尤其是嵌入式操作系统,如各种手机操作系统,低并发web(99.9%网站是低并发),php环境里原生支持SQLite,asp.net/.net winform里可以很方便的使用System.Data.SQLite.
SQLite本身是C写的,自带的API接口也是C接口,所以用C/C++来使用是最直接的了。对于Java语言来说,可以通过SQLite的JDBC接口方式使用SQLite,对于Python,pysqlite是操作SQLite的首选,它已经是Python的标准库之一。
SQLite使用的授权协议时Public Domain协议,可以大胆的使用。
2. 使用SQLite
有几种使用方式,一种是直接把sqlite源码嵌入到系统中去,另一种是通过dll等开发库来调用相关函数接口。下面先介绍源码嵌入的方式。
首先去SQLite官网上面下载最新版的源码,http://www.sqlite.org/download.html,我下载的是sqlite-amalgamation-3080704.zip版本。
解压此压缩包,得到如下几个文件:
,往你的项目里面添加上述文件(除了shell.c文件),然后编译就行。
这样想想,如此强大的SQLite,真正起作用的,只有一个c文件和两个h文件,不由得佩服开发者。在sqlite3.c中实现了全部的SQLite库中的内容,sqlite3.h定义了sqlite3.c的接口函数,因此很容易整合进工程。
然后介绍dll调用开发方式。
在Windows平台下调用SQLite3的接口,可以在上述网站下载 “Precompiled Binariers For Windows”下面的sqlite-dll-win32-x86-XXXX.zip版本,解压后会得到两个文件,
,def文件用来定义一个dll的API导出文件。我们可以根据dll和.def文件来生成一个lib文件,供程序调用。
3. SQLite的接口函数
在SQLite中,有两个核心对象,分别为database_connection和prepared_statement 。
database_connection对象sqlite3 是 通过sqllite3_open()函数创建并返回的,在应用程序使用任何其他SQLite接口函数之前,必须先调用该函数用于初始化数据库。
prepared_statement对象 sqlite3_stmt,可以简单理解为 编译后的SQL语句,所有SQL语句执行相关的函数 都需要该对象作为输入参数用于完成指定SQL操作。
- sqlite3_open 打开一个数据库连接,创建并且返回 sqlite3 对象
- sqlite3_prepare_v2 将制定SQL语句转换成sqlite3_stmt对象
- sqlite3_step 单步执行sqlite3_stmt对象
- sqlite3_column 返回sqlite3_stmt所在行的指定column的值
- sqlite_finalize 销毁sqlite3_stmt对象。所有sqlite3_stmt对象在使用完后必须销毁,防止内存泄露。
- sqlite3_close 关闭数据库连接,销毁sqlite3 对象
- sqlite3_reset 让执行过的sqlite3_step()的sqlite3_stmt重新执行,相当于将游标返回到开始位置重新读取数据,执行效率比新建一个stmt高
- sqlite3_bind 用于INSERT SQL,当同一个INSERT SQL要插入一系列数据时使用,每次sqlite3_step后需要重新bind数据
- sqlite3_exec 封装了一系列执行函数,执行制定的SQL语句,并且将查询结果返回给回调函数。
编程过程中需要注意的地方:
1. 调用sqlite3_exec时,对于第五个参数,errmsg来说,如果sql语句执行出错,那么从内部实现上来看,有如下操作:

内部会调用sqlite3Malloc为pzErrMsg分配内存,并且将对应的错误信息拷贝到pzErrMsg中去,sqlite3_exec函数返回时,通过printf(“%s”,errmsg)来提示具体的错误信息,这里,还需要手动做释放错误提示的内存空间,否则会有内存泄露。
2. sqlite3_exe的回调函数,触发条件为每次成功获取新行后,就会触发回调函数,也就是说,当前表中有多少行符合查询结果,那就调用多少次回调函数。

这是sqlite_exec中具体执行回调函数的语句,它嵌套在while(1)大循环里面,可以看出,如果回调函数返回值不为0的话,即使查询结果是存在的,sqlite_exec会将本次查询结果设置为SQLITE_ABORT,从而打印出错误的函数提示,它将停止后续的查询,直接退出sqlite_exe的while(1)大循环。所以,sqlite_exe中的回调函数,返回值一定要为0,和查询的结果和次数都无关。
对于更新、删除、插入等不需要回调函数的操作,sqlite3_exec的第三、第四个参数可以传入0或者NULL
为了防止垃圾数据,在加载数据库的时候,需要先删除表操作。
const char *sql_drop_table="drop table if exists t";
sqlite3_exec(db,sql_drop_table,0,0,&errmsg);
如果不进行上述操作,同样的插入,每次会在之前表的数据基础上进行。
3. sqlite3_exe中的第五个参数,传入类型是指向指针的指针,所以,如果errmsg定义成 char *errmsg,那么传入参数要写成&errmsg才符合要求。
4. sqlite3_get_table函数用于非回调函数查询结果,这里面,第三个参数比较难理解,先记录如下。

pnRow为查询的有效结果的行数指针,pnColumn为查询的每行有多少列,pzErrmsg为错误提示信息。
pazResult这个需要好好解释一下,它有三个*,它是一个一维数组,以下述的表为例子:
要把,这么些内容全部存在 一维指针数组中,既高效又边界,SQLite中是这样来处理的。
假设char **dbResult; sqlite3_get_table中传入的第二个参数值为 &dbResult,那么,根据上表的构造,select * 查询出来的结果应该是这样的,
nRow = 3,代表结果有3行, nColumn = 2,代表每行有2个字段,dbResult为一维指针数组,共有【(nRow+1)*nColumn】个元素,其内存布局如下:

这样的布局,感觉很巧妙。dbResult的0~nColumn为字段名称,从nColumn索引开始才是真正的数据。
还是一样,我们给进去的只是指针的指针,传出来这么多内容,肯定是需要释放对应的内存。无论非回调的查询是成功还是失败,都必须调用sqlite3_free_table来释放内存,防止内存泄露。
4. 在编写sql语句时,建议设置一个局部较大的数组sqlcmd,采用snprintf(sql_cmd,"CREATE TABLE datapro(package INTEGER,offset \
INTEGER,lklen INTEGER,base INTEHER,link INTEGER,err INTEGER);");来格式化sql命令到数组中去,然后再传入函数。
5. 在执行sqlite_step时,当返回值不为SQLLITE_ROW(此时,代表操作执行成功)时,最好要调用sqlite3_reset来复位内部虚拟机。这是legcy版本的step函数,官方推荐使用v2版本的众多接口函数。
sqlite3_exe类的函数可以完成大部分数据库需求,但是对于插入、查询二进制数据,就无能为力了。对于此类需求,sqlite引入了sqlite3_stmt数据类型,它里面存储被SQLite 解析后的SQL语句内容,因此,可以插入二进制数据,对于表的字段类型为blob类型。
参考链接:
SQLite的官方主页:
http://www.sqlite.org/
SQLite中文站:
http://www.sqlite.com.cn/
System.Data.SQLite:
http://sqlite.phxsoftware.com/
sql学习笔记之 嵌入式数据库(sqlite,firebird)
http://www.cnblogs.com/ljzforever/archive/2010/03/09/1681453.html
SQLite学习心得的更多相关文章
- 我的MYSQL学习心得(一) 简单语法
我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...
- 我的MYSQL学习心得(二) 数据类型宽度
我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...
- 我的MYSQL学习心得(三) 查看字段长度
我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...
- 我的MYSQL学习心得(四) 数据类型
我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(五) 运 ...
- 我的MYSQL学习心得(五) 运算符
我的MYSQL学习心得(五) 运算符 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...
- 我的MYSQL学习心得(六) 函数
我的MYSQL学习心得(六) 函数 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...
- 我的MYSQL学习心得(七) 查询
我的MYSQL学习心得(七) 查询 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...
- 我的MYSQL学习心得(八) 插入 更新 删除
我的MYSQL学习心得(八) 插入 更新 删除 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得( ...
- 我的MYSQL学习心得(九) 索引
我的MYSQL学习心得(九) 索引 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...
随机推荐
- Linux內核中常用的一些延時方法
Linux內核中常用的一些延時方法 這些方法在以下路徑下定義:kernel/include/linux/delay.h #ifndef _LINUX_DELAY_H #define _LINUX_DE ...
- 使用IOCTL代码实现LCD背光调节
国内这种代码找不到.于是參考了相关代码后完好例如以下代码,且实现方式通过IOCTL代码实现LCD背光调节的功能. 适合场合为平板电脑或者笔记本.主要还是要靠BIOS支持与否. 编译环境使用:Dev-c ...
- CSAPP缓冲区溢出攻击实验(上)
CSAPP缓冲区溢出攻击实验(上) 下载实验工具.最新的讲义在这. 网上能找到的实验材料有些旧了,有的地方跟最新的handout对不上.只是没有关系,大体上仅仅是程序名(sendstring)或者參数 ...
- placement new 操作符
placement new操作符能够在分配内存时指定内存位置.下面的程序使用了placement new操作符和常规new操作符给对象分配内存. // placenew.cpp -- new, pla ...
- 关于MIUI悬浮窗权限问题的解决方案
先扯会....好久没写Blog了....这段时间有点小忙...瞎忙.....忙的自己都感觉都不应该.....严重影响了生活质量......生活的幸福指数!!!.....到现在还特么的单身!!!求介绍啊 ...
- kafka彻底删除topic
如果只是用kafka-topics.sh的delete命令删除topic,会有两种情况: 如果当前topic没有使用过即没有传输过信息:可以彻底删除 如果当前topic有使用过即有过传输过信息:并没有 ...
- ASP.NET MVC 之 路由配置
主要操作在App_Start 目录下的 RouteConfig.cs 文件. 一.Url构造方式 1.命名参数规范+匿名对象 routes.MapRoute( name: "Default& ...
- css笔记17:盒子模型加强版的案例
1.先看看经典案例效果图,导出思路: 分析:思路 基本结构 <div> <ul> <li><img src=""/> </li ...
- CSS完成三角形
通过设置div的border属性,来实现! 将div的height和width属性分别设置为0px,将4边的border值设置为一样的宽度,通过调节边框的颜色课看到效果. <style> ...
- linux - 输入输出重定向 及 管道
> 正确结果重定向 2> 错误结果重定向 &> 正确和错误全部重定向 >> 追加,其它同> 标准输出实际上就是显示器,比如我们使用cat命令打开一个文件,文 ...