首页
学习
活动
专区
工具
TVP
发布

SQLite Version 3 Overview

| 编辑注意:本文档是在2004年编写的,作为从SQLite2过渡到SQLite3的程序员的指南。它被保留为SQLite历史记录的一部分。现代程序员应该参考本网站其他地方提供的更新的SQLite最新文档。|

|:----|

  • 数据库文件更紧凑的格式。
  • 清单打字和BLOB支持。
  • 支持UTF-8和UTF-16文本。
  • 用户定义的文本整理序列。
  • 64位ROWID。
  • 改进的并发性。

本文档简要介绍了SQLite 3.0对已经熟悉SQLite 2.8版的用户的更改。

命名更改

在可预见的未来,SQLite 2.8版仍将继续支持bug修复。为了允许SQLite版本2.8和SQLite版本3.0和平共存,SQLite版本3.0中的关键文件和API的名称已被更改为包含字符“3”。例如,C程序使用的包含文件已从“sqlite.h”更改为“sqlite3.h”。用于与数据库交互的shell程序的名称已从“sqlite.exe”更改为“sqlite3.exe”。通过这些更改,可以同时在同一个系统上安装SQLite 2.8和SQLite 3.0。同一个C程序可以同时链接SQLite 2.8和SQLite 3.0,并且可以同时使用这两个库。

新的文件格式

SQLite数据库文件使用的格式已经完全修改。旧版本2.1格式和新版本3.0格式互不兼容。2.8版的SQLite不会读取3.0版的数据库文件,3.0版的SQLite不会读取2.8版的数据库文件。

要将SQLite 2.8数据库转换为SQLite 3.0数据库,请准备好2.8和3.0版的命令行shell。然后输入如下所示的命令:

sqlite OLD.DB .dump | sqlite3 NEW.DB

新的数据库文件格式使用B +树表格。在B +树中,所有数据都存储在树叶中,而不是树叶和中间分支节点中。为表格使用B +树可以实现更好的可扩展性,并且可以在不使用溢出页面的情况下存储更大的数据字段。传统的B树仍然用于索引。

新的文件格式还支持512和65536字节之间的可变页面大小。理论上,页面大小存储在文件头中,因此同一个库可以读取具有不同页面大小的数据库,尽管此功能在实践中尚未实现。

新的文件格式从其磁盘映像中省略了未使用的字段。例如,索引只使用B树记录的关键部分,而不是数据。因此对于索引,省略了记录数据长度的字段。整数值(如密钥长度和数据长度)使用可变长度编码进行存储,因此只需要一个或两个字节来存储最常见的情况,但如果需要,可以编码最多64位信息。整数和浮点数据以二进制形式存储在磁盘上,而不像SQLite 2.8版那样被转换为ASCII。这些更改一起产生的数据库文件通常比SQLite 2.8版中的等效文件小25%至35%。

在SQLite 3.0版中使用的低级B-树格式的细节可以在btreeInt.h源文件的头注释和文件格式文档中找到。

明显的打字和BLOB支持

SQLite版本2.8将在内部处理各种格式的数据,但是当写入磁盘或通过API进行交互时,SQLite 2.8总是将数据转换为ASCII文本。相比之下,SQLite 3.0将其内部数据表示公开给用户,并在适当时将二进制表示存储到磁盘。添加了非ASCII表示的公开以支持BLOB。

SQLite 2.8版的特点是任何类型的数据都可以存储在任何表列中,而不管该列的声明类型如何。该功能在版本3.0中保留,但略有修改。每个表列将存储任何类型的数据,但列对由其声明的数据类型定义的数据格式具有亲和力。将数据插入列时,该列将尝试将数据格式转换为列的声明类型。所有的SQL数据库引擎都这样做。不同的是,即使格式转换不可行,SQLite 3.0仍将存储数据。

例如,如果您有一个声明为“INTEGER”类型的表列,并且您尝试插入一个字符串,那么该列将查看该文本字符串并查看它是否看起来像一个数字。如果字符串看起来像一个数字,它将被转换为一个数字,如果该数字没有小数部分,则将其转换为整数,并以此方式进行存储。但是,如果字符串不是格式正确的数字,它仍然存储为字符串。一个类型为“TEXT”的列在存储之前会尝试将数字转换为ASCII-Text表示。但BLOB作为BLOB存储在TEXT列中,因为通常不能将BLOB转换为文本。

在大多数其他SQL数据库引擎中,数据类型与保存数据的表列相关联 - 与数据容器关联。在SQLite 3.0中,数据类型与数据本身相关联,而不与其容器相关联。Paul Graham在他的书ANSI Common Lisp中称这个属性为“Manifest Typing”。其他作者对术语“显式输入”有其他定义,所以要小心混淆。但无论用什么名字,这都是SQLite 3.0支持的数据类型模型。

有关SQLite版本3.0中数据类型的其他信息单独提供。

支持UTF-8和UTF-16

SQLite 3.0的新API包含以主机本机字节顺序接受文本为UTF-8和UTF-16的例程。每个数据库文件都将文本管理为UTF-8,UTF-16BE(big-endian)或UTF-16LE(小端)。在内部和磁盘文件中,无处不在使用相同的文本表示。如果数据库文件(在文件头中)指定的文本表示与接口例程所需的文本表示不匹配,则文本将被即时转换。不断将文本从一种表示转换为另一种表示可能在计算上花费很大,因此建议程序员选择一种表示并在整个应用程序中使用它。

在当前的SQLite实现中,SQL解析器只能使用UTF-8文本。因此,如果您提供UTF-16文本,它将被转换。这只是一个实现问题,没有什么可以阻止未来版本的SQLite本身解析UTF-16编码的SQL。

当创建新的用户定义的SQL函数和整理序列时,每个函数或整理序列可以指定它是否与UTF-8,UTF-16be或UTF-16le一起工作。可以为每个编码注册单独的实现。如果需要SQL函数或整理序列,但当前文本编码的版本不可用,则会自动转换文本。和以前一样,这种转换需要计算时间,所以程序员应该选择一种编码并坚持下去,以尽量减少不必要的格式杂乱。

SQLite并不特别关注它接收到的文本,并且非常乐意处理未正常化的文本字符串,甚至是格式良好的UTF-8或UTF-16。因此,想要存储IS08859数据的程序员可以使用UTF-8接口。只要不尝试使用UTF-16整理序列或SQL函数,文本的字节顺序将不会被修改。

用户定义的校对序列

整理顺序只是文本的定义顺序。当SQLite 3.0排序(或使用比较运算符,如“<”或“> =”)时,排序顺序首先由数据类型确定。

  • NULL首先排序
  • 数字值按数字顺序排序
  • 文本值在数字之后
  • BLOB最后排序

整理序列用于比较两个文本字符串。整理序列不会改变NULL,数字或BLOB的排序,只会改变文本。

整理序列被实现为一个函数,该函数将两个被比较的字符串作为输入,如果第一个字符串小于,等于或大于第二个字符串,则返回负值,零或正值。SQLite 3.0自带一个名为“BINARY”的内置整理序列,它使用标准C库中的memcmp()例程实现。BINARY整理顺序适用于英文文本。对于其他语言或地区,替代整理序列可能是首选。

决定使用哪个排序顺序由SQL中的COLLATE子句控制。COLLATE子句可以出现在表定义上,用于为表列或索引的字段或SELECT语句的ORDER BY子句定义默认的排序序列。对SQLite的计划增强包括标准的CAST()语法,以允许定义表达式的整理序列。

64位ROWIDs

表格的每一行都有一个独特的rowid。如果表定义了一个类型为“INTEGER PRIMARY KEY”的列,那么该列将成为rowid的别名。但是有或没有INTEGER PRIMARY KEY列,每行仍然有一个rowid。

在SQLite版本3.0中,rowid是一个64位有符号整数。这是SQLite 2.8版的扩展,它只允许32位的rowid。

为了最小化存储空间,64位rowid被存储为一个可变长度整数。0到127之间的Rowid仅使用一个字节。0到16383之间的Rowid仅使用2个字节。最多2097152使用三个字节。等等。负RowID是允许的,但它们总是使用九个字节的存储空间,因此不鼓励使用它们。当rowid由SQLite自动生成时,它们将永远是非负的。

改进的并发性

SQLite版本2.8允许多个同时读取器或一个作者,但不是两者兼而有之。SQLite版本3.0允许一个进程在其他进程继续读取时开始写入数据库。写者必须仍然在数据库上获得一个排它锁,以便在一段短时间内完成其更改,但是整个写操作不再需要排它锁。有关SQLite 3.0版锁定行为的更详细报告可单独提供。

SQLite中现在还有一种有限的表级锁定形式。如果每个表都存储在单独的数据库文件中,则可以将这些单独的文件附加到主数据库(使用ATTACH命令),并且组合的数据库将作为一个功能运行。但锁只会根据需要在单个文件上获取。因此,如果您将“数据库”重新定义为两个或更多数据库文件,那么两个进程完全可以同时写入同一个数据库。为了进一步支持这种功能,涉及两个或多个ATTACHed数据库的事务提交现在是原子的。

积分

SQLite版本3.0部分由AOL开发人员支持和接受优秀的开源软件来实现。

  SQLite在公共领域。

扫码关注腾讯云开发者

领取腾讯云代金券