SQLite使用+简单分析

简介

SQLite 一个非常流行的嵌入式数据库,它支持 SQL 语言,并且只利用很少的内存就有很好的性能。此外它还是开源的,任何人都可以使用它。许多开源项目((Mozilla, PHP, Python)都使用了 SQLite.
SQLite 由以下几个组件组成:SQL 编译器、内核、后端以及附件。SQLite 通过利用虚拟机和虚拟数据库引擎(VDBE),使调试、修改和扩展 SQLite 的内核变得更加方便。
Android 在运行时(run-time)集成了 SQLite,语言接口不使用jdbc而是自己提供api

编译与集成

下载合并包https://www.sqlite.org/download.html
四文件:版本3.28.0

  1. shell.c:用于编译命令行程序
  2. sqlite3.c:数据库全部实现
  3. sqlite3.h:头接口文件
  4. sqlite3ext.h:扩展

添加进VS或直接使用命令行cl编译即可。

使用:
把sqlite3.h、sqlite3ext.h复制到工程目录下,并添加到工程项目中
把sqlite3.lib复制到工程目录下

在cpp文件中加入#pragma comment(lib, “sqlite3.lib”)即可通知编译器链接,这个是VS工具链特有的,gcc下请使用Makefile

代码使用

文档:
https://sqlite.org/cintro.html
https://sqlite.org/c3ref/intro.html

SQLite支持3种线程模式:
  单线程:这种模式下,没有进行互斥,多线程使用不安全。禁用所有的mutex锁,并发使用时会出错。
  多线程:这种模式下,只要一个数据库连接不被多个线程同时使用就是安全的。可以一个线程用一个句柄。
  串行:sqlite是线程安全的。启用所有的锁。

默认是串行的,在编译、运行时都可以更改。

常用的三个接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
sqlite3_open(const char *filename, sqlite3 **ppDb)
该例程打开一个指向 SQLite 数据库文件的连接,返回一个用于其他 SQLite 程序的数据库连接对象。
如果 filename 参数是 NULL 或 ':memory:',那么 sqlite3_open() 将会在 RAM 中创建一个内存数据库,这只会在 session 的有效时间内持续。
如果文件名 filename 不为 NULL,那么 sqlite3_open() 将使用这个参数值尝试打开数据库文件。如果该名称的文件不存在,sqlite3_open() 将创建一个新的命名为该名称的数据库文件并打开。
2 sqlite3_exec(sqlite3*, const char *sql, sqlite_callback, void *data, char **errmsg)
该例程提供了一个执行 SQL 命令的快捷方式,SQL 命令由 sql 参数提供,可以由多个 SQL 命令组成。
在这里,第一个参数 sqlite3 是打开的数据库对象,sqlite_callback 是一个回调,data 作为其第一个参数,errmsg 将被返回用来获取程序生成的任何错误。
sqlite3_exec() 程序解析并执行由 sql 参数所给的每个命令,直到字符串结束或者遇到错误为止。
3 sqlite3_close(sqlite3*)
该例程关闭之前调用 sqlite3_open() 打开的数据库连接。所有与连接相关的语句都应在连接关闭之前完成。
如果还有查询没有完成,sqlite3_close() 将返回 SQLITE_BUSY 禁止关闭的错误消息。

函数返回值表示操作是否正确,如果是SQLITE_OK则表示操作正常。相关的返回值sqlite定义了一些宏。具体这些宏的含义可以参考sqlite3.h 文件。里面有详细定义

核心就是sqlite3_exec了。
用于执行sql语句
参数:数据库句柄、sql语句、回调函数(语句执行后执行)、传递给回调的数据、返回错误信息(将提供的指针指向错误信息)

回调函数:

1
2
3
4
5
6
7
8
9
10
typedef int(*sqlite3_callback)(void*,int,char**,char**);
你的回调函数必须定义成上面这个函数的类型。下面给个简单的例子:
sqlite3的回调函数
sqlite 每查到一条记录,就调用一次这个回调
int LoadMyInfo(void* para,intn_column,char** column_value,char** column_name);
para,调用sqlite3_exec时传递的数据
n_column,是这一条记录有多少个字段(即这条记录有多少列)
char** column_value 查出的字段内容字符串数组,每项是对应列的
char** column_name 跟column_value是对应的,表示这个字段的字段名称

剩下就是命令式的sql语句使用了,按照标准的sql语句实现的。

源码简单分析

文:http://huili.github.io/

除了上层的词法分析、语法分析外,还有一层虚拟机,我个人理解是用于屏蔽事务、数据库管理等提供的顺序操作执行器。
之后是一颗b树、页面缓存与OS接口

这里简单介绍下b树,不同于AVL与红黑,b树一个节点可以有大于等于2个的子节点。插入时若当前同一父下子节点达到临界值,则分列成俩个并提中间向上,因此树是从下至上成长的。