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学习心得(四) 数据类 ...
随机推荐
- GB2312 Unicode转换表实现跨平台utf8转码unicode
在GSM模块中,为发送中文短信,采用pdu发送,需要unicode编码.源程序编辑软件将中文转化为GB2312编码,再下列的GB2312 Unicode转换表转为unicode. 实现2维数值,GB2 ...
- 转自邓凡平 《深入理解Android:Wi-Fi,NFC和GPS》章节连载[节选]--第七章 深入理解Wi-Fi P2P部分节选
本章主要内容: 介绍Wi-Fi P2P相关知识: 介绍Android中WifiP2pService.wpa_supplicant的相关代码. 7.1 概述 承接第6章介绍的WSC,本章将继续介绍Wi ...
- Cocos2d-x学习笔记(10)(CCMenu菜单)
1.CCMenu创建方式 CCMenu* menu = CCMenu::create(cocos2d::CCMenuItem* item,--)參数为CCMenuItem菜单项的对象可变參数列表 2. ...
- 【虚拟化实战】VM设计之一vCPU
作者:范军 (Frank Fan) 新浪微博:@frankfan7 虚拟机需要多少个vCPU呢?是不是个数越多性能越好呢?这方面存在着很多误区.给VM配置CPU资源的时候,要精打细算才能最大可能的利用 ...
- android151 笔记 3
34. 对android虚拟机的理解,包括内存管理机制垃圾回收机制. 虚拟机很小,空间很小,谈谈移动设备的虚拟机的大小限制 16M , 谈谈加载图片的时候怎么处理大图片的,压缩. 垃圾回收,没有引用的 ...
- python---pyc pyo文件详解
http://blog.csdn.net/balabalamerobert/article/details/2683029#comments http://blog.csdn.net/zhengsen ...
- Vesions ignore & ld: library not found for -l...
1.递归删除指定目录下的 .git..svn 文件 find . -name .git | xargs rm -fr find . -name .svn | xargs rm -rf 第一条倒还不常用 ...
- iOS 10 的适配问题
随着iOS10发布的临近,大家的App都需要适配iOS10,下面是我总结的一些关于iOS10适配方面的问题,如果有错误,欢迎指出. 1.系统判断方法失效: 在你的项目中,当需要判断系统版本的话,不要使 ...
- java中关于json传图片的方法
一般来说传图片可以以流的形式来传输,即便是用json传输,一般也都是传一个地址,而图片都存在服务器上,然后顺着地址发送请求下载图片. 但是这次公司的项目中,图片是存在oracle数据库中的blob字段 ...
- Message Decoding
Some message encoding schemes require that an encoded message be sent in two parts. The first part, ...