文章目录

  • 前言
  • 引言
  • 体系结构
    • 接口(interface)
    • 编译器(Compiler)
    • 虚拟机
    • 后端(back-end)
  • SQLite数据库特点
  • 入门
    • SQLite CLP模式种.schema和.tables
    • 数据导出
    • 数据导入
    • 格式化
  • 关系模型
  • SQL语句
    • 创建表
    • 修改表
    • 函数
    • 聚合
    • 分组(Grouping)
    • 去重
    • 多表连接
    • 插入数据
    • 修改数据
    • 删除数据
  • 实体完整性
    • 唯一约束
    • 主键约束
  • 域完整性
    • 默认值
    • 排序法
    • 存储类
    • 事务
    • 事物的范围
    • 冲突解决
    • 数据库锁
    • 死锁
    • 事物种类

前言

这里是阅读的网名为空转大大翻译的SQLITE3书籍翻译的数据是英文版的《The Definitive Guide to SQLite》。因为去看原版英文肯定是要花不少的时间的,所以选择看该作者翻译的书籍,收获颇丰,也希望下面的内容对大家有所帮助。

引言

The author disclaims copyright to this source code.
In place of a legal notice, here is a blessing:
May you do good and not evil.
May you find forgiveness for yourself and forgive others.
May you share freely, never taking more than you give.

这是SQLITE源码的第一段英文,感觉对于一个热爱计算机编程的人来讲非常的有使命感和责任感,希望大家能够共勉

废话不多说直接上干货

体系结构

对于我个人而言,学习一门新的技术栈,最重要的其实不是其使用方法而是其体系结构和编译原理
SQLite拥有一个精致的、模块化的体系结构,并引进了一些独特的方法进行关系型数据库的管理。它由被组织在3个子系统中的8个独立模块组成,如下图。这个模型将查询过程划分为几个不连续的任务,就像在流水线上工作一样。在体系结构栈的顶部编译查询语句,在中部执行它,在底部处理操作系统的存储和接口

接口(interface)

接口由SQLite C API组成,也就是说不管是程序、脚本语言还是库文件,最终都是通过调用它(C API)与SQLite交互的。

编译器(Compiler)

编译过程从分词器(Tokenizer)和分析器(Parser)开始。它们协作处理文本形式的结构化查询(Structured Query Language,SQL)语句,分析其语法有效性,转化为底层能更方便处理的层次数据结构——语法树,然后把语法树传给代码生成器(code generator)进行处理。SQLite分词器的代码是手工编写的,分析器代码由SQLite定制的分析器生成器称为(Lemon)生成的。一旦SQL语句被分解为串值并组织到语法树中,分析器就将该树下传给代码生成器进行处理。而代码生成器根据它生成一种SQLite专用的汇编代码,最后由虚拟机(Virtual Machine)执行。

虚拟机

架构中最核心的部分就是虚拟机,或者叫虚拟数据库引擎(Virtual DataBase Engine,VDBE)。它和Java虚拟机相似,解释执行字节代码。VDBE的字节代码(称为虚拟机语言)由128个操作码构成。主要是进行数据库操作。它的每一条指令或者用来完成特定的数据库操作(比如打开一个表的游标,开始一个事物等),或者为完成这些操作做准备。总之,所有这些指令都是为了满足SQL命令的要求。VDBE的指令集能满足任何复杂SQL命令的要求。

后端(back-end)

后端由B-tree、页缓冲(page cache,pager)和操作系统系统(系统调用)构成。B-tree和page cache共同对数据进行管理。它们操作的是数据库页,这些页具有相同的大小,就像一个集装箱。页里面的“货物”是表示信息的大量bit,这些信息包括记录、字段和索引入口等。B-tree和pager都不知道信息的具体内容,它们只负责“运输”这些页,页不关心这些“集装箱”里面是什么。
B-tree的主要功能就是索引,它维护着各个页之间的复杂关系,便于快速找到所需数据。它把组织成树型的结构(这是它名称的由来),这种树是为查询而高度优化了的。Page为B-tree服务,为他提供页。Pager的主要作用就是通过OS接口在B-tree和磁盘之间传递页
磁盘操作是计算机到目前为止所必须做的最慢的事情。所以,pager尽力提高速度,其方法是把经常使用的页存放到内存当中的也缓冲区里,从而尽量减少操作磁盘的次数。他使用特殊的算法来预测下面要使用那些页,从而使B-tree能够更快地工作。

SQLite数据库特点

零配置:就是不需要DBA(数据库管理员)
简单:使用它只需要引入头文件和源C文件就行
紧凑性:一共不超过240KB
兼容性:支持绝大多数的操作系统
没有限制:开源,完全免费
适应性:作为内嵌形数据库,有强有力可伸缩的关系型数据库前端,和紧凑的B-tree后端。

关系型数据库与非关系型数据库的区别:大家自己百度,一定要区分清除。其实主要就是存储数据结构的方式不同

入门

源码下载地址

SQLite CLP模式种.schema和.tables

.tables[pattern]:返回所有符合条件的视图和表
.schema[table name]:得到一个表或视图定义的DDL语句

数据导出

.dump命令将数据库导出SQL格式的文件。不带参数表示将整个数据库导出。如果提供参数,CLP把参数理解为表名或视图名。

数据导入

有两种方法导入数据,用那种方法决定于要导入的文件格式。如果文件由SQL
语句构成,可以使用.read命令直接导入文件。
如果文件是由逗号或其他界符分割的值(CSV)组成,可以使用.import[file][table]命令。此命令将解析指定的文件并尝试将数据插入到指定的表中。

格式化

CLP提供了几个格式化选项命令。最简单的是.echo,如果设置了.echo on,则新输入的命令在执行前都会回显,默认值是off。.headers设置为on时,查询结果显示时带有字段名。当遇到NULL值时,如果需要以一个字符串来显示,使用.nullvalue命令设置。
如果要改变CLP的shell提示符,使用.prompt[value]
.mode命令可以设置结果数据的几种输出格式。可选的格式为csv、column、html、insert、line、list、tabs和tcl。默认值是list。在此模式下显示结果实例以默认的分隔符进行分割。
可通过.separator命令进行设置。
可通过dbname VCUUM来释放数据库中未被使用的空间。

关系模型

详解关系模型
关系型与非关系型模型区别
SQLITE极限
table->tuples(行)->arrtibutes(列)

在SQL中,创建和删除数据库对象的语句一般被称为数据定义语言(data definition language,DDL),操作这些对象中数据的语句称为数据操作语言(data manipulation language,DML)。创建表的语句属于DDL

SQL语句

创建表

CREATE TABLE contacts ( id INTEGER PRIMARY KEY,
name TEXT NOT NULL COLLATE NOCASE,
phone TEXT NOT NULL DEFAULT ‘UNKNOWN’,
UNIQUE (name,phone) );

修改表

ALTER TABLE table { RENAME TO name | ADD COLUMN column_def }

函数

SQLite 提供了多种内置的函数和聚合,可以用在不同的子句中。函数的种类包括:数学函数,如 ABS()计算绝对值;字符串格式函数,如 UPPER()和 LOWER(),它们将字符串的值转化为大写或小写。函数名是不分大小写的(或 upper()和 UPPER()是同一个函数)。

聚合

聚合是一类特殊的函数,它从一组记录中计算聚合值。标准的聚合函数包括 SUM()、AVG()、COUNT()、MIN()和 MAX()。

分组(Grouping)

聚合的精华部分是分组。聚合不只是能够计算整个结果集的聚合值,你还可以把结果集分成多个组,然后计算每个组的聚合值。这些都可以在一步当中完成,方法就是使用 GROUP BY子句。

去重

操作管道中的下一个限制是 DISTINCT。DISTINCT 处理 SELECT 的结果并过滤掉其中重复的行。

多表连接

连接(join)是 SELECT 命令的第一个操作,它产生初始的信息,供语句的其它部分过滤和处
理。连接的结果是一个合成的关系(或表),它是 SELECT 后继操作的输入。

插入数据

INSERT INTO table (column_list) VALUES (value_list);

修改数据

UPDATE table SET update_list WHERE predicate;

删除数据

DELETE FROM table WHERE predicate;

实体完整性

唯一约束

UNIQUE

UNIQUE与NULL的关系:
问题:如果一个字段已经声明为UNIQUE,可以向这个字段插入多少NULL值?
SQLite采用了与PostgreSQL和 Oracle 相同的解决方案。,可以插入多个NULL

问题2:两个NULL值是否相等
你没有足够的信息来证明它们相等,但也没有足够的信息证明它们不等。SQLite 的观点是假设所有的 NULL都是不同的。所以你可以向唯一字段中插入任意多个 NULL 值。

主键约束

在 SQLite 中,当你定义一个表时总要确定一个主键,不管你自己有没有定义。这个字段是一个 64-bit 整型字段,称为 ROWID。它还有两个别名——_ROWID_和 OID,用这两个别名同样可以取到它的值。它的默认取值按照增序自动生成。SQLite 为主键字段提供自动增长特性。

域完整性

默认值

保留字 DEFAULT 为字段提供一个默认值。如果用 INSERT 语句插入记录时没有为该定做指定值,则为它赋默认值。DEFAULT 不是一个约束(constraint),因为它没有强制任何事情。这所以把它归为域完整性,是因为它提供了处理 NULL 值的一个策略。如果一个字段没有指定默认址,在插入时也没有为该字段指定值,SQLite 将向该字段插入一个 NULL。

排序法

排序法定义如何唯一地确定文本的值。排序法主要用于规定文本值如何进行比较。不同的排序法有不同的比较方法。例如,某种排序法是大小写不敏感的,于是'JujyFruit'和'JUJYFRUIT'被认为是相等的。另外一个排序法或许是大小写敏感的,这时上面两个字符串就不相等了。SQLite 有 3 种内置的排序法。默认为 BINARY,它使用一个 C 函数 memcmp()来对文本进行逐字节的比较。

存储类

事务

事务定义了一组SQL命令的边界,这组命令或者作为一个整体被全部执行,或者都不执行。
典型代表就是转账

事物的范围

事物由3个命令控制:BEGIN、COMMIT和ROLLBACK。BEIGIN开始一个事物,之后所有操作都可以取消。COMMIT使BEGIN后的命令 得到确认;而ROLLBACK还原BEGIN之后的所有操作。
SQLite默认情况下,每条SQL语句自成事物(自动提交模式)

冲突解决

当违反约束导致事物的非法结束时,大多数数据库(管理系统)都是简单地将前面所做地修改全部取消掉。
SQLite有其独特的方法来处理约束违反(或说从约束违反中恢复),称为冲突解决。

数据库锁

SQLite 采用粗放型的锁。当一个连接要写数据库,所有其它的连接被锁住,直到写连接结束了它的事务。SQLite 有一个加锁表,来帮助不同的写数据库都能够在最后一刻再加锁,以保证最大的并发性。

SQLite 使用锁逐步上升机制,为了写数据库,连接需要逐级地获得排它锁。SQLite 有 5 个
不同的锁状态:未加锁(UNLOCKED)、共享(SHARED)、保留(RESERVED)、未决(PENDING)和排它(EXCLUSIVE)。每个数据库连接在同一时刻只能处于其中一个状态。每种状态(未加锁状态除外)都有一种锁与之对应。

最初的状态是未加锁状态,在此状态下,连接还没有存取数据库。当连接到了一个数据库,甚至已经用 BEGIN 开始了一个事务时,连接都还处于未加锁状态。
未加锁状态的下一个状态是共享状态。为了能够从数据库中读(不写)数据,连接必须首先进入共享状态,也就是说首先要获得一个共享锁。多个连接可以同时获得并保持共享锁,也就是说多个连接可以同时从同一个数据库中读数据。但哪怕只有一个共享锁还没有释放,也不允许任何连接写数据库。如果一个连接想要写数据库,它必须首先获得一个保留锁。一个数据库上同时只能有一个保留锁保留锁可以与共享锁共存,保留锁是写数据库的第1 阶段保留锁即不阻止其它拥有共享锁的连接继续读数据库,也不阻止其它连接获得新的共享锁
一旦一个连接获得了保留锁,它就可以开始处理数据库修改操作了,尽管这些修改只能在缓冲区中进行,而不是实际地写到磁盘。对读出内容所做的修改保存在内存缓冲区中。当连接想要提交修改(或事务)时,需要将保留锁提升为排它锁。为了得到排它锁,还必须首先将保留锁提升为未决锁。获得未决锁之后,其它连接就不能再获得新的共享锁了,但已经拥有共享锁的连接仍然可以继续正常读数据库。此时,拥有未决锁的连接等待其它拥有共享
锁的连接完成工作并释放其共享锁。一旦所有其它共享锁都被释放,拥有未决锁的连接就可以将其锁提升至排它锁,此时就可以自由地对数据库进行修改了。所有以前对缓冲区所做的修改都会被写到数据库文件.

死锁


如上图,A连接到数据库,处于未加锁状态,B也连接到数据库,也处于未加锁状态,当A进行select语句时,读取数据库,此时A获得一个共享锁,而B因为需要对数据库进行写操作,因此在A已经处于共享锁状态时,所以B先处于保留锁状态,对缓冲区进行操作,但是B执行了COMMIT操作,B将保留锁提升到未决锁状态,阻隔其他新的连接得到共享锁,在提升到排他锁,发现A未释放掉共享锁状态,依旧在读取数据库,因此无法升级为排他锁,所以无法写数据库。锁升级失败!退回到未决锁状态,阻隔其他进程获取共享锁。而A执行完select语句后,想要写数据库,因为B为释放保留锁,而数据库中只能有一个保留锁,因此A获取保留锁失败。

事物种类

SQLite 有三种不同的事务,使用不同的锁状态。事务可以开始于:DEFERRED、MMEDIATE或 EXCLUSIVE。事务类型在 BEGIN 命令中指定:
BEGIN [ DEFERRED | IMMEDIATE | EXCLUSIVE ] TRANSACTION;
一个 DEFERRED 事务不获取任何锁(直到它需要锁的时候),BEGIN 语句本身也不会做什么事情——它开始于 UNLOCK 状态。默认情况下就是这样的,如果仅仅用 BEGIN 开始一个事务,那么事务就是 DEFERRED 的,同时它不会获取任何锁;当对数据库进行第一次读操
作时,它会获取 SHARED 锁;同样,当进行第一次写操作时,它会获取 RESERVED 锁。由 BEGIN 开始的 IMMEDIATE 事务会尝试获取 RESERVED 锁。如果成功,BEGINIMMEDIATE 保证没有别的连接可以写数据库。但是,别的连接可以对数据库进行读操作;
但是,RESERVED 锁会阻止其它连接的 BEGIN IMMEDIATE 或者 BEGIN EXCLUSIVE 命
令,当其它连接执行上述命令时,会返回 SQLITE_BUSY 错误。这时你就可以对数据库进行修改操作了,但是你还不能提交,当你 COMMIT 时,会返回 SQLITE_BUSY 错误,这意味着还有其它的读事务没有完成,得等它们执行完后才能提交事务。EXCLUSIVE 事务会试着获取对数据库的 EXCLUSIVE 锁。这与 IMMEDIATE 类似,但是一
旦成功,EXCLUSIVE 事务保证没有其它的连接,所以就可对数据库进行读写操作了。上节那个例子的问题在于两个连接最终都想写数据库,但是它们都没有放弃各自原来的锁,最终,SHARED 锁导致了问题的出现。如果两个连接都以 BEGIN IMMEDIATE 开始事务,
那么死锁就不会发生。在这种情况下,在同一时刻只能有一个连接进入BEGIN IMMEDIATE,其它的连接就得等待。BEGIN IMMEDIATE 和 BEGIN EXCLUSIVE 通常被写事务使用。就像同步机制一样,它防止了死锁的产生。

基本的准则是:如果你正在使用的数据库没有其它的连接,用 BEGIN 就足够了。但是,如
果你使用的数据库有其它的连接也会对数据库进行写操作,就得使用 BEGIN IMMEDIATE
或 BEGIN EXCLUSIVE 开始你的事务

深入浅出SQLITE3相关推荐

  1. Python --深入浅出Apriori关联分析算法(二) Apriori关联规则实战

    上一篇我们讲了关联分析的几个概念,支持度,置信度,提升度.以及如何利用Apriori算法高效地根据物品的支持度找出所有物品的频繁项集. Python --深入浅出Apriori关联分析算法(一) 这次 ...

  2. 如何在sqlite3连接中创建并调用自定义函数

    #!/user/bin/env python # @Time :2018/6/8 14:44 # @Author :PGIDYSQ #@File :CreateFunTest.py '''如何在sql ...

  3. Sqlite3支持的数据类型 日期函数 Sqlite3 函数

    Sqlite3支持的数据类型 NULL INTEGER REAL TEXT BLOB 但实际上,sqlite3也接受如下的数据类型: smallint 16 位元的整数. interger 32 位元 ...

  4. MSDN Webcast“深入浅出ASP.NET AJAX系列”

    课程: ASP.NET AJAX深入浅出系列课程(1):ASP.NET AJAX 概述(3月13日):对于ASP.NET AJAX的大致功能进行概述和演示,通过简单的演示让听众了解到ASP.NET A ...

  5. linux qt 连接sqlite3,RedHat 9 Linux下在QT3.1中连接SQLite3全过程详细记录

    作者:zieckey([email]zieckey@yahoo.com.cn[/email]) All Rights Reserved 下文介绍的内容都是基于 Linux RedHat 9.0 平台的 ...

  6. 在CentOS 7.5上升级SQLite3过程实录

    业务起因 我在CentOS 7.5上安装python3.7+Django 3.1.7并创建项目时,发现启动demo例子出错了,出错信息如下: django.core.exceptions.Improp ...

  7. SQLite3简单C++包装类源码示例

    一个比较好的SQLite3 C++ wrapper包装类的通常思路是这样的: 数据库连接类,包含连接池,和sqlite3*,负责与数据库文件的连接问题: 一些create table,insert,u ...

  8. 5.3Role和Claims授权「深入浅出ASP.NET Core系列」

    5.3Role和Claims授权「深入浅出ASP.NET Core系列」 原文:5.3Role和Claims授权「深入浅出ASP.NET Core系列」 希望给你3-5分钟的碎片化学习,可能是坐地铁. ...

  9. 【数据库】sqlite3数据库备份、导出方法汇总

    [数据库]sqlite3常用命令及SQL语句 目录 1.直接拷贝数据库 2.使用.backup .clone 1)交互式 2)脚本 3.导出到csv文件中(其它格式类似) 1)交互式 2)脚本 3)导 ...

  10. 【数据库】sqlite3常用命令及SQL语句

    [数据库]sqlite3数据库备份.导出方法汇总 一.准备工作 0.安装SQLite3 1)ubuntu命令安装(不是最新版本) sudo apt install sqlite3 2)源码安装(可以安 ...

最新文章

  1. css实现 textarea 高度自适应
  2. 在人工智能领域,人工智能机器无法如人一样理解常识知识
  3. 100G 免费技术学习资料大全分享 (2020 年最新)
  4. 用Android Studio调试Framework层代码
  5. Android 中文API (46) —— SimpleAdapter
  6. 01-Eureka是什么?
  7. 字典和键值对换输出_Python知识小结—字典
  8. Bzoj4542--Hnoi2016大数
  9. python基础6-控制语句
  10. 5.2刚买了佳能的ixus100is数码相机,可以录像不过是mov格式的,需要转换为dvd的软件...
  11. 13. Django基础:admin后台管理
  12. Ubuntu基础命令(五)--创建、复制、移动、删除
  13. 五种经典网页布局设计
  14. Python 爬取zw年鉴
  15. python进阶方向_python进阶—边练边学,学到极致
  16. mysql建表与oracle_mysql和oracle建表语句以及数据类型的区别
  17. 2018.12.3比赛题目:电子警察
  18. 自学python从字符串开始吧
  19. 【Xgen UE】将Xgen制作好的毛发导入UE
  20. python集合为什么不能用下标运算_Python的Set操作,python,集合

热门文章

  1. 靶机渗透练习81-Momentum:2
  2. 上海职称英语计算机取消,上海地区职称英语考试是不是取消了?
  3. hdu5385 wyh2000 and pupil 二分图
  4. photoshop ps 替换图片文字
  5. 捷径越来越少,快钱越来越难,为什么人生的路越来越窄?
  6. Gabor滤波器详解
  7. D-028 DDR3硬件电路设计
  8. python获取交互式ssh shell
  9. vector subscript out of range数组下标越界错误
  10. 大数据分析服务器硬件配置如何选择