SQLite 是一个遵守 ACID(即原子性、一致性、隔离性和持久性)的关系数据库管理系统,它包含在一个很小的 C 程序库中。与许多其他数据库管理系统不同,SQLite 不是一个 C/S 结构的数据库引擎,而是被集成在用户程序中。应用程序通过编程语言内的直接 API 调用来使用 SQLite 的功能,这在减少数据库访问延迟上有积极作用,因为,在一个单一进程中的函数调用比跨进程通信更有效率。
它采用了在写入数据时将整个数据库文件加锁的简单设计。尽管写操作只能串行进行,但 SQLite 的读操作可以多任务同时运行。
SQLite 优点:
(1)零配置,无需安装和配置;
(2)储存在单一磁盘文件中的一个完整数据库;
(3)数据库文件可以在不同字节顺序的机器间自由共享;
(4)支持数据库大小 2TB;
(5)足够小,全部源代码大致 3 万行 C 代码,250KB;
(6)比目前流行的大多数数据库对数据的操作要快;
(7)开源。
SQLite 数据库采用模块化设计,这些独立模块又构成了 3 个主要的子系统:
SQLite 前端解析系统,分为 3 个模块,词法解析器、语法分析器、代码生成器:
1、词法分析器(Tokenizer)
当执行一个包含 SQL 语句的字符串时,接口程序要把这个字符串传递给 tokenizer。Tokenizer 的任务是把原有字符串分割成一个个标识符(token),并把这些标识符传递给解析器。
2、语法分析器(Parser)
语法分析器的工作是在指定的上下文中赋予标识符具体的含义。SQLite 的语法分析器使用 Lemon LALR(1) 分析程序生成器来产生,Lemon 做的工作与 YACC/BISON 相同,但它使用不同的输入句法,这种句法更不易出错。Lemon 还产生可重入的并且线程安全的语法分析器。Lemon 定义了非终结析构器的概念,当遇到语法错误时它不会泄露内存。
3、代码生成器(Code Generator)
语法分析器在把标识符组装成完整的 SQL 语句后,就调用代码生成器产生虚拟机代码,以执行 SQL 语句请求的工作。
SQLite 后端引擎,后端是用来解释字节编码程序的引擎,该引擎做的才是真正的数据库处理工作。后端部分主要由三个模块组成:
1、虚拟机(Virtual Machine)
代码生成器生成的代码由虚拟机来执行。虚拟机实现一个专为操作数据库文件而设计的抽象计算引擎。它有一个存储中间数据的存储栈,每条指令包含一个操作码和不超过三个额外的操作数。它把数据库看成表和索引的集合,而表和索引则是一系列的元组合记录。
2、B - 树(B-Tree)
一个 SQLite 数据库使用 B - 树的形式存储在磁盘上。数据库中的每个表和索引使用一棵单独的 B - 树,所有的 B - 树存放在同一个磁盘文件中。该模块帮助 VM 进行搜索,插入和删除树中的元组。
3、页面高速缓存(Page Cache)
B - 树模块以固定大小的数据块形式从磁盘上请求信息,默认的块大小是 1024 个字节,但是可以在 512 和 65536 个字节之间变化。页面高速缓存负责读、写和缓存这些数据块。页面高速缓存还提供回滚和原子提交的抽象,并且管理数据文件的锁定。B - 树驱动模块从页面高速缓存中请求特定的页,当它想修改页面、想提交或回滚当前修改时,它也会通知页面高速缓存。页面高速缓存处理所有麻烦的细节,以确保请求能够快速、安全而有效地被处理。
SQLite 基本数据类型:
NULL:标识一个 NULL 值
INTERGER:整数类型
REAL:浮点数
TEXT:字符串
BLOB:二进制数
Sqlite 常用约束条件如下:
PRIMARY KEY - 主键:
1)主键的值必须唯一,用于标识每一条记录,如学生的学号
2)主键同时也是一个索引,通过主键查找记录速度较快
3)主键如果是整数类型,该列的值可以自动增长
NOT NULL - 非空:
约束列记录不能为空,否则报错
UNIQUE - 唯一:
除主键外,约束其他列的数据的值唯一
CHECK - 条件检查:
约束该列的值必须符合条件才可存入
DEFAULT - 默认值:
列数据中的值基本都是一样的,这样的字段列可设为默认值
数据库的创建事实上并非通过 SQL 语句来创建,创建数据库可以通过以下命令实现:
- sqlite3 school.db
- create [temp|temporary] table table_name(field1 type1, field2 type1, ...);
- 如果在table前面加上temp或者temporary,表示建立临时表,临时表会在这次连接会话结束时自动销毁,table_name是要创建数据表名称,fieldx是数据表内字段名称,typex则是字段类型。
- 例,建立一个简单的学生信息表,它包含学号与姓名等学生信息:
- create table student_info(stu_no interger primary key autoincrement, name text);
在 SQLite 中,一个表中必须有一个主键,默认情况下,SQLite 表中都含有一个内置的主键,它是一个 64 位的整型字段,称为 rowid。支持自动增长(autoincreament)。
例,
- create table student_info(stu_no interger primary key autoincrement, name text);
外键能确保表中的关键值必须在另一个表中引用,且数据必须在另一个表中存在,否则会操作失败或引起连锁反应。其中,外键引用的表称为父表,含有外键子段的表称为子表。
外键约束格式:
- FOREIGN KEY (子表中的列) REFERENCES 父表(父表中的子段)
如果程序中需要使用外键约束,可以在 SQLOpenHelper 类中的 onOpen 函数中启用:
- @Override
- public void onOpen(SQLiteDatabase db) {
- // TODO Auto-generated method stub
- super.onOpen(db);
- if (!db.isReadOnly()) {
- // Enable foreign key constraints 开启外键约束
- db.execSQL("PRAGMA foreign_keys=ON;");
- }
- }
- insert into table_name(field1, field2, ...) values(val1, val2, ...);
- valx为需要存入字段的值。
- 例,往学生信息表添加数据:
- Insert into student_info(stu_no, name) values(0001, alex);
(1)批量插入数据,字段一样:
- insert into stu select * from students;
(2)批量插入,字段不一样:
- insert into stu(name, tel_no) select name,
- tel_no from students;
(3) 批量插入,字段不一样:
- create table stu as select * from students;
- select指令基本格式:
- select columns from table_name [where expression];
- a查询输出所有数据记录
- select * from table_name;
- b限制输出数据记录数量
- select * from table_name limit val;
- 查询students表中的从3的位置检索1条数据
- select * from students limit 1 offset 2;
- c升序输出数据记录
- select * from table_name order by field asc;
- d降序输出数据记录
- select * from table_name order by field desc;
- e条件查询
- select * from table_name where expression;
- select * from table_name where field in ('val1', 'val2', 'val3');
- select * from table_name where field between val1 and val2;
- f查询记录数目
- select count (*) from table_name;
- g区分列数据
- select distinct field from table_name;
- 有一些字段的值可能会重复出现,distinct去掉重复项,将列中各字段值单个列出。
- h常用逻辑操作符,and、or、not;
- i模糊匹配,查询t开头的记录
- select * from students where name like "t%";
- j分组Group by,having(限制条件)
- select count(*) ,cls_id from students where group by cls_id having cls_id>2;
- update table_name set field1=val1, field2=val2 where expression;
- where是sql语句中用于条件判断的命令,expression为判断表达式
- 例,修改学生信息表学号为0001的数据记录:
- update student_info set stu_no=0001, name=hence where stu_no=0001;
- delete from table_name [where expression];
- 不加判断条件则清空表所有数据记录。
- 例,删除学生信息表学号为0001的数据记录:
- delete from student_info where stu_no=0001;
(1) 多表连接
数据关系通常需要跨越多个表,因此,多表查询变得尤为重要。
- select * from students,
- classes where students.cls_id = classes.id;
(2) 内连接
内连接使用关系代数交叉操作,根据指定的条件筛选出两个表的子集。因此,使用内连接进行查询时,只有两个表中都符合条件的数据时该条数据才会被检索到。
- select * from students inner join classes on students.cls_id = classes.id;
内连接添加了 inner join 关键字,并且用 on 关键字取代了 where 语句。
(3)左外连接
左外连接与内连接的语法相似,只是将 inner join 换成 left outer join。它与 inner join 的区别是如果条件不匹配,那么它的结果集中会返回左表中的数据,右表中的数据将由字段类型的空值填充。
- select * from students left outer join classes on students.cls_id = classes.id;
注意:除了左外连接之外,实际上标准的 SQL 还有右外连接、全外连接。右外连接的特点是左表中有不匹配的则用空值代替,全外连接则是有任何一方存在不匹配数据则用空值代替。
对于 SQLite,它只支持内连接和左外连接。
索引是用于加速查询结构。默认情况下,当我们按照指定的条件查询表中的数据时会扫描所有的行来找到匹配数据。如果我们的表比较大,且这个查询使用的频率比较高,就可以为这个查询条件指定的列创建索引。
- 当说数据表存在大量记录,索引有助于加快查找数据表速度。
- create index index_name on table_name(field);
- 例,针对学生表stu_no字段,建立一个索引:
- create index student_index on student_table(stu_no);
- 建立完成后,sqlite3在对该字段查询时,会自动使用该索引。
- drop table table_name;
- drop index index_name;
触发器的作用是当特定的表发生特定的操作时进行预定义的操作,创建触发器的通用命令是:
- CREATE TRGGER delete_trig AFTER delete
- ON students
- BEGIN
- INSERT INTO delete_log(stu_id,stu_name) VALUES (old.id,old.name);
- END;
意思是当从 students 表中删除数据时,会将被删除学生的 id、名字添加到 delete_log 表中,学生 id、名字分别用 old.id,old.name 表示。
事务是一个数据库操作的执行单元。它定义了一条或多条 SQL 语句,这些语句要么被全部执行,要么不全部执行,它保证了多条 SQL 语句的原子性。
事务有 begin、commit、rollback3 个命令,begin 表示开始一个事务、commit 表示整个事务操作成功、rollback 表示回滚到 begin 之前。
格式:
- // SQL语句
- [commit|rollback];
本文主要介绍 SQLite 的架构和 SQL 语句使用,下篇文章重点介绍 SQLite 在 Android 开发中的使用。
来源: http://www.bubuko.com/infodetail-1947952.html