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://blog.csdn.net/ztchun/article/details/55195969