SQLite 学习笔记
SQLite 学习笔记.
一.SQLite 安装
访问http://www.sqlite.org/download.html下载对应的文件.
1.在 Windows 上安装 SQLite.需要下载 sqlite-shell-win32-*.zip 和 sqlite-dll-win32-*.zip 压缩文件.
创建文件夹 C:\sqlite,并在此文件夹下解压上面两个压缩文件,将得到 sqlite3.def、sqlite3.dll 和 sqlite3.exe 文件.
添加 C:\sqlite 到 PATH 环境变量,最后在命令提示符下,使用 sqlite3 命令,将显示如下结果.
C:\>sqlite3
SQLite version 3.7.15.2 2013-01-09 11:53:05
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite>
2.在 Linux 上安装 SQLite
几乎所有版本的 Linux 操作系统都附带 SQLite.所以,只要使用下面的命令来检查您的机器上是否已经安装了 SQLite.
如果没有安装,则需要从源代码区下载 sqlite-autoconf-*.tar.gz.
$tar xvfz sqlite-autoconf-3071502.tar.gz
$cd sqlite-autoconf-3071502
$./configure --prefix=/usr/local
$make
$make install
二.SQLite 命令
在命令行下输入sqlite3进入sqlite shell模式.后面可接一个文件名,用于创建本地文件(在当前目录中,如命令提示符启动时的目录),否则只在内存中处理.
.help 或 .h : 查询帮助信息,返回可用的命令. 也可以在命令行中输入sqlite3 -help,在命令行中输出sqlite的相关信息.
.exit 或 .e 或 .quit 或 .q : 退出sqlite模式
.backup ?DB? FILE 备份 DB 数据库(默认是 "main")到 FILE 文件。
.bail ON|OFF 发生错误后停止。默认为 OFF。
.databases 列出附加数据库的名称和文件。
.dump ?TABLE? 以 SQL 文本格式转储数据库。如果指定了 TABLE 表,则只转储匹配 LIKE 模式的 TABLE 表。
.echo ON|OFF 开启或关闭 echo 命令。
.exit 退出 SQLite 提示符。
.explain ON|OFF 开启或关闭适合于 EXPLAIN 的输出模式。如果没有带参数,则为 EXPLAIN on,及开启 EXPLAIN。
.header(s) ON|OFF 开启或关闭头部显示。
.import FILE TABLE 导入来自 FILE 文件的数据到 TABLE 表中。
.indices ?TABLE? 显示所有索引的名称。如果指定了 TABLE 表,则只显示匹配 LIKE 模式的 TABLE 表的索引。
.load FILE ?ENTRY? 加载一个扩展库。
.log FILE|off 开启或关闭日志。FILE 文件可以是 stderr(标准错误)/stdout(标准输出)。
.mode MODE 设置输出模式,MODE 可以是下列之一:
csv 逗号分隔的值
column 左对齐的列
html HTML 的 <table> 代码
insert TABLE 表的 SQL 插入(insert)语句
line 每行一个值
list 由 .separator 字符串分隔的值
tabs 由 Tab 分隔的值
tcl TCL 列表元素
.nullvalue STRING 在 NULL 值的地方输出 STRING 字符串。
.output FILENAME 发送输出到 FILENAME 文件。
.output stdout 发送输出到屏幕。
.print STRING... 逐字地输出 STRING 字符串。
.prompt MAIN CONTINUE 替换标准提示符。
.read FILENAME 执行 FILENAME 文件中的 SQL。
.schema ?TABLE? 显示 CREATE 语句。如果指定了 TABLE 表,则只显示匹配 LIKE 模式的 TABLE 表。
.separator STRING 改变输出模式和 .import 所使用的分隔符。
.show 显示各种设置的当前值。
.stats ON|OFF 开启或关闭统计。
.tables ?PATTERN? 列出匹配 LIKE 模式的表的名称。
.timeout MS 尝试打开锁定的表 MS 微秒。
.width NUM NUM 为 "column" 模式设置列宽度。
.timer ON|OFF 开启或关闭 CPU 定时器测量。
创建数据库 命令行输入"sqlite3 文件名",即创建了一个数据库.但是这个文件不会立即创建,需等到添加数据,或退出sqlite时才保存.
三.SQLite 语法
1.命令: 每条命令由一系列的记号组成,以";"结束.记号可以是常量,关键字,标识符,表达式或特殊符号.
2.常量: 字符串常量,数字常量,二进制常量.
字符串常量以单引号引起来.也可以是双引号,但SQL标准是单引号,所以建议都使用单引号.
数字常量可以是整数,如1,-1,2.3等.
二进制常量使用x'0000'的表示方法.其中每位是一个16进制数.二进制值必须是16进制数的整数倍(8bits),如x'1f',x'2312',x'ffeedd'
3.关键字和标识符: 不区分大小写.关键字不能作为标识符使用.如select,update,insert,into,create,drop,begin等等.
4.注释: 以--开头,或/* */形式包含
四.SQL命令
1.创建表.create table
create [temp|temporary] table table_name (column_definitios [,constaraints]);
temp或temporary声明的是临时表,只存活于当前会话,连接断开时自动销毁.
方括号内是可选项.
管道符|表示2选1;
必须包含至少一个表和一个字段.table_name为表名,小括号内是字段名列表,字段之间以","分隔.每个字段由"名称 类型 约束条件(可选)"组成.
例如,如下创建了contacts表,其中_id是自增主键,name声明为text,约束不能为null,且排序不区分大小写.phone默认为UNKNOWN.表一级约束是unique,定义在name和phone上.
CREATE TABLE contacts( _id integer primary key autoincrement,
name text not null collate nocase,
phone text not null default 'UNKNOWN',
unique(name,phone) );
2.修改表.alter table可以修改表名或增加字段
alter table table_name {rename to new_table_name | add column colunm_def};
大括号内表示可选项,只能2选1.语句中并不需要包含大括号.
colunm_def为新增的列定义,与create table要求一致.
例如,如下新增一个列email.
alter table contacts add column email text not null default ' ';
表还可以由select语句创建,这样在创建表结构的同时创建数据.
3.插入数据. insert into
(1)插入单行
insert into table_name(column_list) values (value_list);
insert into table_name values(value_list); 此形式中value_list中的值需要与创建表的字段一一对应.
table_name为插入的表名. column_list表示需要插入的列列表,value_list是对应的值列表,它们都用","分隔.字段必须存在于表中.如
sqlite> insert into phone(contacts_id, data) values(2, 223);
在column_list不指定自增长的字段(primary key autoincrement),或指定了但value_list对应的值为null,则该字段会自动增长.
(2)插入一组行
使用子查询添加: 在value_list中对某一个数据采用子查询的方式,得到一组值.如
insert into phone values(null, (select _id from contacts), null);
使用select形式的insert语句可以一次插入多行,只要数据字段匹配.
sqlite> CREATE TABLE phone2 (_id integer primary key autoincrement, contacts_id integer);
sqlite> insert into phone2 select phone._id,phone.contacts_id from phone;
(3)插入多行数据
创建时插入数据.create table new_table_name as select * from table_name.这样将复制table_name一份数据到新到表new_table_name中.
如 sqlite> create table phone3 as select * from phone2;
但是,这种形式创建的新表,原约束及类型都不是旧表的类型.自增字段不会创建,索引也不会创建,unique也不会有.
4.更新数据. update
update table_name set update_list where predicate;
update_list是一个或多个赋值字段的列表,形式为:column1=value1,column2=value2,...
where子句和select命令相同.
如: sqlite> update phone set data = 10087, contacts_id = 4 where _id == 3;
update命令必须注意unique约束,如不能修改primary key的值为重复项,否则会报错.
5.删除记录 delete
delete from table_name where predicate;
where子句和select命令相同.不带where子句的语句将删除整个表.
注意:
(1)delete语句删除后并不释放空间.
(2)primary key autoincrement字段的最大值也不会恢复为0,会保留旧值,如需恢复,需要删除或更新sqlite_sequence下的值.
sqlite> delete from phone where _id = 14;
5.查询数据库.select命令.select命令输出可作为另一个select的输入,如select name from (select * from contacts).
select [distinct] heading from tables where predicate group by columns having predicate order by columns limit count offset count;
每个关键字如from,where,having,group by,order by,limit等都是一个单独的子句,每个子句由关键字和跟随的参数构成.后面的子句以前面子句产生的结果进行输入处理.
distinct去掉重复.
select distinct name from contacts;语句将列出name,所有行的name值都不一样.
from子句是由逗号分隔的一个或多个表,视图.如果指定多个表,它们会组合形成单一的关系.
where子句参数predicate由逻辑表达式组成,它们定义了行的选择标准.
如select * from contacts where _id < 3 and email != ' ';
逻辑表达式中,可以包由以下几种组成
(1)比较指定条件,如==(或=),!=(或<>),>,<,>=,<=,!<(不小于),!>(不大于).
(2)逻辑运算符
AND 运算符允许在一个 SQL 语句的 WHERE 子句中的多个条件的存在.
BETWEEN 运算符用于在给定最小值和最大值范围内的一系列值中搜索值.
EXISTS 运算符用于在满足一定条件的指定表中搜索行的存在.
IN 运算符用于把某个值与一系列指定列表的值进行比较.
NOT IN 运算符的对立面,用于把某个值与不在一系列指定列表的值进行比较.
LIKE 运算符用于把某个值与使用通配符运算符的相似值进行比较,不区分大小写.如 like '%h%' 将选出该值中包含h的.
GLOB 运算符用于把某个值与使用通配符运算符的相似值进行比较,大小写敏感的即区分大小写。
NOT 运算符是所用的逻辑运算符的对立面。比如 NOT EXISTS、NOT BETWEEN、NOT IN,NOT LIKE等等。它是否定运算符。
OR 运算符用于结合一个 SQL 语句的 WHERE 子句中的多个条件。
IS NULL 运算符用于把某个值与 NULL 值进行比较。
IS 运算符与 = 相似。
IS NOT 运算符与 != 相似。
|| 连接两个不同的字符串,得到一个新的字符串。
UNIQUE UNIQUE 运算符搜索指定表中的每一行,确保唯一性(无重复).
在LIKE和GLOB中,%可匹配0个或多个任意字符,_可匹配一个任意字符.
(3)位运算符
& 如果同时存在于两个操作数中,二进制 AND 运算符复制一位到结果中.
| 如果存在于任一操作数中,二进制 OR 运算符复制一位到结果中.
~ 二进制补码运算符是一元运算符,具有"翻转"位效应.
<< 二进制左移运算符。左操作数的值向左移动右操作数指定的位数.
>> 二进制右移运算符。左操作数的值向右移动右操作数指定的位数.
GROUP BY子句用于与 SELECT 语句一起使用,来对相同的数据进行分组.
产生的效果是,指定列不会出现两个重复的值.如name字段都含有"中国移动",则只会出现一个.
利用聚合函数,还可以对每个组的数据计算聚合值.如
select name,count(*) from contacts group by name;语句将显示不同的name出现的次数
HAVING 子句允许指定条件来过滤将出现在最终结果中的分组结果.例如,以下语句将选出字段name相同且个数大于2的数据.
select * from contacts group by name having count(2) > 2;
order by子名指定以某些列进行排序.asc升序(默认),desc降序.当第一个出现重复时,以后面第二,第三,...去排序.
limit和offset限定大小和范围.limit指定返回的最大记录数量.offset指定偏移的记录数.
limit和offset一起使用时,可以使用","代替offset.注意:limit 2,1表示的是limit 1 offset 2.
多级选择
语法:select ... from left_table_name join_type right_table_name on join_condition;
实例:
sqlite> create table phone (_id integer primary key autoincrement, contacts_id integer, data text);
sqlite> select contacts.name, phone.data from contacts,phone where contacts._id = phone.contacts_id;
(1)内连接,找出同时存在于两个表中的元素.
select ... from table_1 inner join table_2 on conditional_expression ...;
sqlite> select * from contacts inner join phone on contacts._id = phone.contacts_id;
(2)交叉连接,不需要连接条件,只是简单的组合在一起.
SELECT ... FROM table_1 CROSS JOIN table2 ...
sqlite> select * from contacts cross join phone;
(3)外连接(OUTER JOIN)是内连接(INNER JOIN)的扩展.SQL标准定义了三种类型的外连接:LEFT\RIGHT\FULL,但SQLite只支持左外连接(LEFT OUTER JOIN).
左外连接 SELECT ... FROM table1 LEFT OUTER JOIN table2 ON conditional_expression ...;
sqlite> select * from contacts left outer join phone on contacts._id = phone.contacts_id;
左外连接试图把所有contacts中_id与phone中contacts_id相同的所有行进行连接关系的匹配,找出所有匹配的行.但是contacts中没有匹配phone的行仍会出现在结果中,phone中没有提供相应的行,以null补充.
(4)自然连接,通过表中共有的字段名将两个表连接起来.因此使用自然连接时,不用添加连接条件就能取得内连接的结果.
自然连接由于两个表的列改动而出现结果的不确定性,因此尽量不使用.
名称和别名.
连接表时,如果两个表中存有同样名称的字段时,如使用select _id就会产生歧义.因此可用 table_name.field 的方法避免.
另一种方式是使用别名.如select f._id, t._id from contacts f, phone t where f._id == t.contacts_id;
其中contacts 的别名是f,phone的别名是t.
条件结果.
第一种,接收静态值并列出各种情况下的case返回值.
case value
when x then value_x
when y then value_y
else default_value
end
sqlite> select name || '_' || case _id when 1 then 'a' else 'b' end description from contacts where length(description) > 6 order by _id;
其中||用于连接两个字符串,返回的值为description,where对description进行过滤.
第二种,允许when条件中有表达式.
case
when condition_1 then value_x
when condition_2 then value_y
else default_value
end
sqlite> select name || '_' || case when _id < 3 then 'a' else 'b' end description from contacts where length(description) > 6 order by _id;
函数.
SQLite提供了多种内置函数和聚合,可以用在不同的子句中.函数包括:数学函数如abs,字符串格式函数,和大小写转换函数upper及lower.
聚合是一类特殊的函数,它从一组记录中计算聚合值.如sum,avg,count,min,max等
select _id,upper(name),length(name) from contacts; 以_id,upper(name),length(name)分别显示每行数据.
select * from contacts where length(name) > 4; 选出name长度大小4的行
select count(*) from contacts; 计算所有行的数量.
聚合还可以把结果集分成多个组,然后计算每个组的聚合值.
处理 null值.
null是缺失信息的占位符,本身不是值,也不是空字符串.简单的说,null就是null.NOT NULL 表示列总是接受给定数据类型的显式值,这意味着不能为null.
(1)逻辑运算中的null.
AND: true AND null = null. false AND null = false. null AND null = null.
OR: true OR null = true. false OR null = null. null OR null = null.
其中true可用值为非0或非0的逻辑表达式代替,false用0或值为0的逻辑表达式代替.
可以使用select语句测试,如select null and 1;
(2)可以通过 is null 或 is not null 检测null是否存在.
(3)null不等于其它值,包括null.因此不能使用equal,greater than等函数进行比较.
(4)coalesce函数: 返回非null的第一个值.如sqlite> select coalesce (null, 1, null, 8); 将返回1
(5)nullif函数: 如果两个数相等则返回null,否则返回1.如
sqlite> select nullif(1, 1);
null
sqlite> select nullif(1, 3);
1
(6)使用null,需要注意断言和聚合中引用可能存在null值字段的查询.否则可能报错.
五.约束
1.unique唯一性约束.要求一个或一组字段所有值互不相同.
如下表中,id在每行中都不能相同.name和phone不能同时相同.
sqlite> create table phone5(id integer unique, name text not null default '', phone text not null default 'UNKNOWN', unique(name, phone));
在sqlite中,null与null都不相同,因此可以同时放入两个null.
2.primary key主键约束.每个表只有一个主键,称为rowid(别名_rowid,oid),如果在创建表时指定了primary key约束,那么它就是rowid的另一个别名.
主键具有自动增长的功能.SQLite使用64位单符号整数主键,因此,最大值为0x7fffffffffffffff.达到最大值时rowid会回收已删除的值.
但指定了autoincrement的主键则不会,SQLite也会在一个名为sqlite_sequence的系统表中记录该字段当前的最大值.达到最大值时,后面的insert语句中返回SQLITE_FULL错误.
sqlite_sequence中保存两个字段,name为表名,seq为自动主键的最大值.
主键约束也可以定义在多个字段中,此时同唯一性约束.如
create table pkey(x text, y text, primary key(x, y));
SQLite总是在内部维护rowid,因此建议使用实际字段作为主键字段,即创建表时定义主键字段.
3.default 默认值.保证该字段有值,并在需要时出现.如果没有默认值,insert语句中没有指定值,则为null.default还可以指定三种默认的格式:
default current_time 生成当前时间 (HH:MM:SS)
default current_data 生成当前日期 (YYYY-MM-DD)
default current_timestamp 生成一个日期时间的组合 (YYYY-MM-DD HH:MM:SS)
如下面的语句:
sqlite> create table phone7(name text, time1 text not null default current_time, time2 text not null default current_date, time3 text not null default current_timestamp);
sqlite> insert into phone7(name) values('haha');
sqlite> .headers on
sqlite> .mode column
sqlite> select * from phone7;
name time1 time2 time3
---------- ---------- ---------- -------------------
haha 14:15:12 2016-01-20 2016-01-20 14:15:12
4.not null 约束.确保该字段不为null.insert语句中不能向该字段插入null,update语句也不能修改为null.
使用not null约束的字段,如果没有指定default,则在insert时必须向该字段赋值,因为系统提供的默认值是null.
处理未知数据和not null约束的实用方法是给字段设定默认值.这样就insert语句就可以安全的使用默认值,也可以将null排除在外.
5.check 约束.允许定义表达式来测试要插入或者更新的字段值.如果该值不满足表达式的标准,则会报约束违反错误.可直接在字段后面写约束条件,或者作为表定义中的一条单独约束.
sqlite> create table phone9(_id integer primary key autoincrement, phone text check( length( phone ) > 7) );
或 sqlite> create table phone9(_id integer primary key autoincrement, phone text, check( length(phone) > 7 ));
sqlite> insert into phone9(phone) values('123');
Error: CHECK constraint failed: phone9
check 表达式可以根据字段的值进行评估.如:
sqlite> create table foo(x integer, y integer check(y>x), z integer check (z>abs(y)));
6.外键约束.确保一个表中的关键值必须从另一个表中引用,且该数据必须在另一个表中实际存在.如父子关系,主从关系,以及订单和商品关系等.
语法: create table table_name(column_definition references foreign_table_name(column_name) on {delete|update} integrity_action [not] deferrable [initially{deferred|immediate},] ... );
如:
sqlite> CREATE TABLE food_types(id integer primary key, name text);
sqlite> CREATE TABLE foods(id integer primary key, type_id integer references food_types(id) on delete restrict deferrable initially deferred, name text);
references foreign_table_name(column_name): 表示关联的表中的字段.
on delete 或 on update: 删除或添加时的行为.
integrity_action: 行为规则.如下
set null: 如果父值被删除了或者不存在,剩余的子值将改为null.
set default: 如果父值被删除了或者不存在,子值修改为默认值.
cascade: 更新父值时,更新力有预知匹配的子值.删除父值时,删除所有子值.注意:删除功能可能会出现意想不到的效果.
restrict: 更新或删除父值时,阻止或终止事务.
no action: 只观察变化,不做任何变化.
deferrable initially deferred或immediate: deferred延迟到事务结束执行,immediate立即执行.
在windows平台下,测试外键约束,没有起作用.
7.排序规则.collate关键字定义排序的规则.
(1)binary(默认),使用c函数memcmp逐字节进行比较,因此是大小写敏感的.
(2)nocase,大小写不敏感的的排序.
(3)reverse,与默认规则相反,用来测试.
CREATE TABLE seq(_id integer primary key autoincrement, data1 text, data2 text collate nocase, data3 text collate reverse);
8.存储类,即原始的5个基本类型integer,real,text,blob,null
NULL NULL值.
INTEGER 整数,根据值的大小存储在 1、2、3、4、6 或 8 字节中.
REAL 实数,存储为8字节的IEEE浮点数字.
TEXT 文本字符串,使用数据库编码(UTF-8、UTF-16BE 或 UTF-16LE)存储.默认最大值为 1000,000,000 字节.
BLOB blob数据,完全根据它的输入存储.默认最大值为 1000,000,000 字节.
SQLite判断类型的方法和顺序:
语句中用""或''包含的文字为text.
只有数字,没有小数点或浮点数符号,为integer,否则为real.
null或NULL表示null值.
格式为x'ABCD'或X'ABCD',其中ABCD为16进制数,则为blob.
函数typeof方法可返回值的类型.
sqlite> select typeof('sss');
typeof('sss')
一个字段定义为了某个存储类,但仍可能存储其它存储类的值.排序时采用以下规则:
(1)null为最小值.任何非null值都null值大.null值之间没有具体的排序顺序.
(2)integer和real通过数值大小进行比较排序.
(3)text比integer或real值大,text之间由字段定义的排序规则进行比较.
(4)blob比text值大,blob之间采用c memcmp()函数比较.
9.索引.索引是用来在某种条件下加速查询的结构.索引会增加数据库的大小;对表insert,update,delete修改时,也需要对相应的索引进行修改.
语法: create [unique] index index_name on table_name (columns);
index_name是索引名称,columns是table_name中的字段,以","分隔.
columns中也可以指定对列排序.
unique要求索引中的所有值必须是唯一的.这会在insert或update时,要求相应的字段不能同时相同.
删除索引: drop index index_name;
查询表的索引: .schema table_name 或 .indices table_name
注意: 一定要在理由能确保索引可提高性能时才使用索引,以下几个情况都应该避免使用索引:
在较小的表上; 在有频繁的大批量的更新或插入操作的表上; 在含有大量的 NULL 值的列上; 在频繁操作的列上。
六.触发器.事件发生时,触发器负责启动SQL命令.当触发器相关联的表删除时,自动删除触发器
语法:
create [temp|temporary] trigger trigger_name [before|after] [insert|update|update of columns] on table_name
begin
action
end;
before|after: 指定是在事件发生前还是发生后执行.
insert|update|update of columns: 事件在表table_name中执行的命令.
action:具体要回调执行的行为,由一系列的SQL命令组成.
如下例:
CREATE TABLE foo(a integer primary key autoincrement, b text, c text, d text collate nocase);
CREATE TRIGGER foo_insert after insert on foo
begin
update foo set c=b, d=b;
end;
更新触发器,可以在表的某个字段上定义,这样在该字段有修改行为时,会自动触发相应的trigger.
create trigger trigger_name [before|after] update of column on table begin action end;
CREATE TRIGGER foo_update after update of b on foo
begin
update foo set c=b, d=b;
end;
七.事务
事务由3个命令控制:begin,commit,rollback.
begin: 开始一个事务,begin之后的所有操作都可以取消.如果连接终止前没有发出commit,也会被取消.
语法: begin [deferred | immediate | exclusive] transaction; 或 begin; 相当于deferred
commit: 提交事务,执行所有begin到commit之间的所有操作.
rollback: 取消所有操作.
如果不显示的使用这3个命令,SQLite中每条命令都会自动使用begin...commit/rollback,如果执行成功则执行ommit自动提交,出错则rollback回滚.
savepoint pos ,保存执行的点.使用 rollback to pos ,可恢复到 pos以前的状态.
1.冲突解决.SQLite提供了5种可能的冲突解决策略.默认策略为abort.
replace: 违反唯一性约束时,将记录删除,以插入或修改的新记录代替,SQL继续执行,不报错.但删除触发器不会触发.
违反 not null 约束时, 使用该字段的默认值代替null.如果没有默认值,则使用abort策略.
ignor: 约束违反时,命令继续执行,违反约束的行不变.不报错.
fail: 约束违反时,终止命令,但不恢复违反之前已修改的记录.
abort: 约束违反时,恢复到命令所做的所有改变,并终止.
rollback:约束违反时,执行回滚,终止当前命令和整个事务.这将导致单个约束违反引起整个事务中执行的所有操作都回滚.
2.冲突使用.冲突可以在insert, update, create table, create index中指定.如
insert or resolution into table_name ....
update or resolution table_name ....
在表定义时也可为某个字段指定冲突,在约束中增加 on conflict resolution, 如
sqlite> create temp table cast(id integer unique on conflict rollback);
3.数据库锁
数据库锁有5种状态,每个连接在同一时刻只能有一种状态,除了未加锁,都有一个锁与之对应.
未加锁(unlocked): 数据库初始状态,此时没有访问数据库,即使调用了begin开始事务也如此.
共享(shared): 一个连接想读数据,首先需要取得共享锁.多个读数据连接可以同时取得共享锁,即共享锁可以有多个.
预留(reserved): 一个连接想写数据,首先需要取得预留锁,同一时刻只能有一个预留锁.预留锁不会阻止其它连接取得共享锁.
取得预留锁之后可以写数据,此时数据保存在缓冲区,并不保存到数据库文件.
未决(pending): 写数据连接提交数据时会先取得未决锁,此时其它连接不能取得共享锁,
但拥有共享锁的连接还可继续读数据,写数据连接等到所有共享锁释放后提升为排它锁.
排它(exclusive): 写数据连接需要取得排它锁时,才能往数据库文件中保存数据.
4.事务的类型
deferred: 直到使用时才获取锁,多个连接可以在同一时刻未创建锁的情况下开始deferred事务.
这种方式下,第一个读数据连接取得共享锁,第一个写数据连接取得保留锁.
immediate: 采用这种方式,会在begin时试图取得预留锁.如果成功,其它连接不能写数据,也不阻止已取得共享锁的连接读数据,但会阻止新的连接读数据.
此时,其它任务执行事务begin [immediate | exclusive]将会返回SQLITE_BUSY错误.
同时,如果其它读事务没有退出时,也不能提交,否则也会返回SQLITE_BUSY错误.
exclusive: 采用这种方式,会试图取得排它锁.一旦成功,其它连接就不能读写,此时可进行任意的读写操作.
使用的准则是,如果数据库没有其它连接,使用begin就足够了,但是如果存在其它写数据连接,就得使用immediate或exclusive开始事务.
八.其它常见问题
1.自动主键增加到Long最大值时再添加数据会报错Error: database or disk is full.
在Android中会报异常,android.database.sqlite.SQLiteFullException: database or disk is full (code 13).
遇到这种情况下,需要在删除表的同时将自动主键的值进行重新设置.
如何将自增字段的值重新设置为1.字段带有primary key autoincrement约束的表,sqlite将为其创建一个隐藏的表sqlite_sequence.
sqlite_sequence记录了当前数据库文件中所有表的自动主键的最大值.删除表后删掉该值或设置为0即可重置表的自动主键值.
如contacts2.db的信息如下表.
sqlite> select * from sqlite_sequence;
name seq
---------- ----------
mimetypes 20
directorie 1
accounts 8
raw_contac 1799
data 6425
contacts 2639
groups 12
agg_except 1122
data_usage 90
calls 620
photo_file 3
执行语句:
sqlite> delete from calls;
sqlite> update sqlite_sequence set seq = 0 where name == 'calls'; 或 delete from sqlite_sequence where name == 'calls';
2.Android中如何取得自增字段的最大值?
select last_insert_rowid();语句在android中将返回0.
可用以下语句代替: select max(primary_key_column) from table_name;或 查询sqlite_sequence表.如
sqlite> select max(_id) from contacts;
max(_id)
4
在Android中示例代码如下:
public long getMaxId() {
long id = 0;
SQLiteDatabase db = null;
try {
db = mSqliteHelper.getWritableDatabase();
String sql;
// sql = "select * from sqlite_sequence";
sql = "SELECT max(_id) as max_id FROM " + PersonSQLiteHelper.TABLE_NAME;
Cursor cursor = db.rawQuery(sql, null);
if (cursor != null) {
if (cursor.moveToNext())
id = cursor.getLong(0);
cursor.close();
}
} finally {
if (db != null)
db.close();
}
return id;
}
SELECT max(_id) FROM table_name;
参考资料:http://www.runoob.com/sqlite/sqlite-null-values.html
《SQLite权威指南(第2版)》
SQLite 学习笔记的更多相关文章
- SQLite学习笔记(七)&&事务处理
说到事务一定会提到ACID,所谓事务的原子性,一致性,隔离性和持久性.对于一个数据库而言,通常通过并发控制和故障恢复手段来保证事务在正常和异常情况下的ACID特性.sqlite也不例外,虽然简单,依然 ...
- Sqlite学习笔记(四)&&SQLite-WAL原理
Sqlite学习笔记(三)&&WAL性能测试中列出了几种典型场景下WAL的性能数据,了解到WAL确实有性能优势,这篇文章将会详细分析WAL的原理,做到知其然,更要知其所以然. WAL是 ...
- Sqlite学习笔记(四)&&SQLite-WAL原理(转)
Sqlite学习笔记(三)&&WAL性能测试中列出了几种典型场景下WAL的性能数据,了解到WAL确实有性能优势,这篇文章将会详细分析WAL的原理,做到知其然,更要知其所以然. WAL是 ...
- sqlite学习笔记7:C语言中使用sqlite之打开数据库
数据库的基本内容前面都已经说得差点儿相同了.接下看看如何在C语言中使用sqlite. 一 接口 sqlite3_open(const char *filename, sqlite3 **ppDb) 打 ...
- Sqlite学习笔记(一)&&编译安装
Sqlite简介 sqlite是一个开源的嵌入式文件数据库,sqlite以动态链接库的方式供应用程序调用,所有的数据库对象都存储在同一个文件中. sqlite动态库非常小,最新的3.8.11版本也只有 ...
- SQLite学习笔记(十)&&加密
随着移动互联网的发展,手机使用越来越广泛,sqlite作为手机端存储的一种解决方案,使用也非常普遍.但是sqlite本身安全特性却比较弱,比如不支持用户权限,只要能获取到数据库文件就能进行访问:另外也 ...
- SQLite学习笔记(十二)&&虚拟机指令
上篇文章简单讨论了虚拟机的原理,这篇文章我们详细讨论下指令,具体从几种典型的SQL语句来看看每种SQL对应的指令流,以及每个指令的含义.通过explain语句,可以看到语句对应的指令流:通过pragm ...
- SQLite学习笔记(十一)&&虚拟机原理
前言 我们知道任何一种关系型数据库管理系统都支持SQL(Structured Query Language),相对于文件管理系统,用户不用关心数据在数据库内部如何存取,也不需要知道底层的存储 ...
- SQLite学习笔记(九)&&pager模块
概述 通过上一篇文章的分析,我们知道了pager模块在整个sqlite中所处的位置.它是sqlite的核心模块,充当了多种重要角色.作为一个事务管理器,它通过并发控制和故障恢复实现事务的ACID特性, ...
随机推荐
- [Clr via C#读书笔记]Cp12泛型
Cp12泛型 Generic: 特点 源代码保护 类型安全 清晰代码 更佳性能 Framework中的泛型 System.Collections.Generic; 开放类型,封闭类型:每个封闭类型都有 ...
- Python面向对象-访问限制
在Class内部,可以有字段,方法和属性,而外部代码可以通过直接调用实例变量的方法来操作数据, (1)私有普通字段 比如对于下面的Student类,name字段可以在外面通过对象进行直接访问: cla ...
- Python面向对象-类成员
类的成员可以分为三大类:字段.方法和属性: 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段.而其他的成员,则都是保存在类中,即:无论对象的多少,在 ...
- 基础数据类型-list
序列是python中的基础数据结构,序列里每一个元素都有一个下标,从0开始,依次递增. list,tuple,dictionary是使用最频繁的三类数据结构. (1)序列都有的方法包括:索引,切片,检 ...
- return阻止js继续向下执行
终止JS运行有如下几种可能: 终止函数的运行的方式有两种 在函数中使用return,则当遇到return时,函数终止执行,控制权继续向下运行 在函数中使用try-catch异常处理,需要结束时,使用t ...
- POJ 2823 (滑动窗口)
这道题最容易想到的是用朴素的做法,即 每滑动一次,就遍历一次窗口找出最大最小值,这样时间复杂度为O(n*k),由于题目数据比较大,这种做法肯定是超时的. 另外,根据书上的讲解,还可以采用优先队列来求解 ...
- 最长回文子串计算(fail)
题意: 给定一个字符串s,在s中找到最长的回文子字符串.您可以假设s的最大长度为1000. 例子: 输入: “babad” 输出: “bab” 注: “aba”也是一个有效的答案. 我的答案: 想法: ...
- lintcode-152-组合
152-组合 组给出两个整数n和k,返回从1......n中选出的k个数的组合. 样例 例如 n = 4 且 k = 2 返回的解为: [[2,4],[3,4],[2,3],[1,2],[1,3],[ ...
- 【week2】 词频统计效能分析
效能统计工具:Jprofiler License Key:L-Larry_Lau@163.com#23874-hrwpdp1sh1wrn#0620 该性能分析工具对服务器进行监听,图一是线程变化图,当 ...
- 安装django 提示ImportError: No module named setuptools
安装django前要先安装setuptools 先安装一些必要的包,否则会报错:Python build finished, but the necessary bits to build these ...