SQLite3命令操做大全

SQLite3命令操做大全html

SQLite库包含一个名字叫作sqlite3的命令行,它可让用户手工输入并执行面向SQLite数据库的SQL命令。本文档提供一个样使用sqlite3的简要说明.node

一.qlite3一些经常使用Sql语句操做

建立表:            create  table 表名(元素名 类型,…);android

删除表:            drop  table 表名;             git

插入数据:       insert  into 表名 values(, , ,) ;  sql

建立索引:       create [unique] index 索引名on 表名(col….);shell

删除索引:   drop index 索引名(索引是不可更改的,想更改必须删除从新建)
删除数据:       delete from 表名;              数据库

更新数据:       update 表名 set 字段=’修改后的内容’ where 条件; 服务器

增长一个列:  Alter table 表名 add column 字段 数据类型;  网络

选择查询:       select 字段(以”,”隔开) from 表名 where 条件; 数据结构

日期和时间: Select datetime('now')

日期:   select date('now');       
时间:  select time('now');  

总数select count(*) from table1;
求和select sum(field1) from table1;
平均select avg(field1) from table1;
最大select max(field1) from table1;
最小select min(field1) from table1;

排序select 字段 from table1 order by 字段(descasc)  ;(降序或升序)

分组select 字段 from table1 group by 字段,字段  ;

限制输出:select 字段fromtable1 limit x offset y;

                          = select 字段 from table1 limit y , x;

(备注:跳过y行,取x行数据)

 

(操做仍待完善)…

SQLite支持哪些数据类型些?

NULL       值为NULL
INTEGER 值为带符号的整型,根据类别用1,2,3,4,6,8字节存储
REAL        值为浮点型,8字节存储
TEXT        值为text字符串,使用数据库编码(UTF-8, UTF-16BE or UTF-16-LE)存储
BLOB       值为二进制数据,具体看实际输入

但实际上,sqlite3也接受以下的数据类型:
smallint  16 位元的整数
interger                     32 位元的整数
decimal(p,s)  p 精确值和 s 大小的十进位整数,精确值p是指所有有几个数(digits)大小值 ,s是指小数点後有几位数。若是没有特别指定,则系统会设为 p=5; s=0 。
float                  32位元的实数。
double              64位元的实数。
char(n)             n 长度的字串,n不能超过 254。
varchar(n)       长度不固定且其最大长度为 n 的字串,n不能超过 4000。
graphic(n)        和 char(n) 同样,不过其单位是两个字元 double-bytes, n不能超过127。这个形态是为了支援两个字元长度的字体,例如中文字。
vargraphic(n)  可变长度且其最大长度为 n 的双字元字串,n不能超过 2000。
date                  包含了 年份、月份、日期。
time                  包含了 小时、分钟、秒。
timestamp      包含了 年、月、日、时、分、秒、千分之一秒。

若是将声明表的一列设置为 INTEGER PRIMARY KEY,则具备:

1.每当你在该列上插入一NULL值时, NULL自动被转换为一个比该列中最大值大1的一个整数;

2.若是表是空的, 将会是1;

算术函数

abs(X)返回给定数字表达式的绝对值。

max(X,Y[,...])返回表达式的最大值。

min(X,Y[,...])返回表达式的最小值。

random(*)返回随机数。

round(X[,Y])返回数字表达式并四舍五入为指定的长度或精度。

字符处理函数

length(X)返回给定字符串表达式的字符个数。

lower(X)将大写字符数据转换为小写字符数据后返回字符表达式。

upper(X)返回将小写字符数据转换为大写的字符表达式。

substr(X,Y,Z)返回表达式的一部分。

randstr()

quote(A)

like(A,B)

肯定给定的字符串是否与指定的模式匹配。

glob(A,B)

条件判断函数

coalesce(X,Y[,...])

ifnull(X,Y)

nullif(X,Y)

集合函数

avg(X)返回组中值的平均值。

count(X)返回组中项目的数量。

max(X)返回组中值的最大值。

min(X)返回组中值的最小值。

sum(X)返回表达式中全部值的和。

其余函数

typeof(X)返回数据的类型。

last_insert_rowid()返回最后插入的数据的 ID 。

sqlite_version(*)返回 SQLite 的版本。

change_count()返回受上一语句影响的行数。

last_statement_change_count()

二.有关事务的操做

(成批操做的时候,启动事务,比不启动事务快n倍)

开始事物处理

BEGIN  TRANSACTION;

…………..

进行对数据库操做

…………..

事物提交

COMMIT;

具体事例以下:

假设有一个 t1 表,其中有 "a", "b", "c" 三列, 若是要删除列 c ,如下过程描述如何作:

BEGIN TRANSACTION;
CREATE TEMPORARY TABLE t1_backup(a,b);
INSERT INTO t1_backup SELECT a,b FROM t1;
DROP TABLE t1;
CREATE TABLE t1(a,b);
INSERT INTO t1 SELECT a,b FROM t1_backup;
DROP TABLE t1_backup;
COMMIT;[h1] 

三.启动sqlite3程序

仅仅须要敲入带有SQLite数据库名字的"sqlite3"命令便可。若是文件不存在,则建立一个新的(数据库)文件。而后 sqlite3程序将提示你输入SQL。敲入SQL语句(以分号“;”结束),敲回车键以后,SQL语句就会执行。
    例如,建立一个包含一个表"tb11"名字为"ex1"的SQLite数据库,你能够这样作:
数据库、表的创建,记录的添加、查询、修改和删除
F:\>sqlite3 database.db
sqlite> create table admin(username text,age integer);
sqlite> insert into admin values('kuang',25);
sqlite> select * from admin;
sqlite> update admin set username='kk',age=24 where username='kuang' and age=25;
sqlite> delete from admin where username='kk';
注:每条sql语句后必须以";"号结尾!
$sqlite3 ex1
SQLite version 3.3.17
Enter ".help" for instructions
sqlite> create table tbl1(one varchar(10), two smallint);
sqlite> insert into tbl1 values('hello!', 10);
sqlite> insert into tbl1 values('goodbye', 20);
sqlite> select * from tbl1;
hello!|10
goodbye|20
sqlite>
        你能够经过敲你所用系统的文件结束符(一般是Ctrl + D)或者中断字符(一般是Ctrl + C)。来终止sqlite3程序。肯定你在每一个SQL语句结束敲入分号!sqlite3程序经过查找分号来决定一个SQL语句的结束。若是你省略分 号,sqlite3将给你一个连续的命令提示符并等你给当前的SQL命令添加更多的文字。这个特色让你输入多行的多个SQL语句,例如:
sqlite> create table tbl2(
   ...> f1 varchar(30) primary key,
   ...> f2 text,
   ...> f3 real
   ...> );
sqlite>

四.题外话:查询SQLITE_MASTER表

    SQLite数据库的框架被保存在一个名叫"sqlite_master"的特殊的表中。你能够像查询其它表同样经过执行“SELECT”查询这个特殊的表。例如:
$ sqlite3 ex1
SQlite vresion 3.3.10
Enter ".help" for instructions
sqlite> select * from sqlite_master;
     type = table
     name = tbl1
tbl_name = tbl1
rootpage = 3
      sql = create table tbl1(one varchar(10), two smallint)
sqlite>
    但你不能在sqlite_master表中执行诸如DROP TABLE, UPDATE, INSERT 或者DELETE命令。sqlite_master表在你建立、删除和索引数据库时自动更新这个表。你不能手工更改sqlite_master表。
    TEMPORARY表的结构没有存储在"sqlite_master"表中,因为TEMPORARY表对应用是不可见的,而不是应用程序建立这个表。 TEMPORARY表结构被存储在另一个名叫"sqlite_temp_master"的特定的表中。"sqlite_temp_master"表是临 时表自身。

五.sqlite3的特殊命令

   大多数候,sqlite3读入输入行,并把它们传递到SQLite库中去运行。可是若是输入行以一个点(“.”)开始,那么这行将被sqlite3程序自 己截取并解释。这些“点命令”一般被用来改变查询输出的格式,或者执行鞭个预封包(预约义prepackaged)的查询语句。
你能够在任什么时候候输入“.help”,列出可用的点命令。例如
sqlite> .help

.bail ON|OFF            

Stop after hitting an error.  Default OFF(遇到错误时再也不继续, 默认为OFF)

.databases               

 List names and files of attached databases(列出附加到数据库的数据库和文件)

.dump ?TABLE? ...          

Dump the database in an SQL text format(保存表到SQL格式的文件中, 没有指表名, 则保存全部. 若是要保存到磁盘上须要结合 .output 命令.)

.echo ON|OFF              

Turn command echo on or off(打开/关闭 命令行回显)

.exit                          

Exit this program(退出该命令行)

.explain ON|OFF           

Turn output mode suitable for EXPLAIN on or off.( 以合适的方式显示表头, 不带参数则为开启)

.header(s) ON|OFF       

Turn display of headers on or off(是否显示表头, 和 .explain 差异不是很大)

.help                       

Show this message(显示帮助信息)

.import FILE TABLE         

Import data from FILE into TABLE(从文件中导入表)

.indices TABLE              

Show names of all indices on TABLE(显示索引)

.load FILE ?ENTRY?        

Load an extension library(加载一个扩展库)

.mode MODE ?TABLE?      

Set output mode where MODE is one of:

 

(设置输出模式, 模式能够是如下几种):
                          csv       Comma-separated values( 以逗号分隔的值)
                          column    Left-aligned columns.   (See .width)( 表头左对齐(参见 .width))
                          html      HTML <table> code(显示 HTML 代码)
                          insert    SQL insert statements for TABLE( SQL插入语句)
                          line      One value per line( 一行一个值)
                          list      Values delimited by separator string(值用 string 分隔)
                          tabs      Tab-separated values(以 tab 分隔的值)
                          tcl       TCL list elements(TCL 列表元素)

.nullvalue STRING      

Print STRING in place of NULL values(以 STRING 代替 NULL 值的输出)

.output FILENAME        

Send output to FILENAME(输出到文件, 而不是显示在屏幕上)

.output stdout          

Send output to the screen(输出到屏幕上)

.prompt MAIN CONTINUE  

Replace the standard prompts(替换默认的命令提示信息, 默认就是 sqlite>)

.quit                     

Exit this program(退出命令行)

.read FILENAME        

Execute SQL in FILENAME(执行 FILENAME 中的 SQL语句)

.schema ?TABLE?        

Show the CREATE statements(显示 CREATE 语句)

.separator STRING      

Change separator used by output mode and .import

.show                    

Show the current values for various settings(显示各类设置)

.tables ?PATTERN?      

List names of tables matching a LIKE pattern(查看数据库的表列表)

.timeout MS            

Try opening locked tables for MS milliseconds(在 MS 时间内尝试打开被锁定的表)

.width NUM NUM ...      

Set column widths for "column" mode(设置 column 模式中的列的宽度)

 

.timer ON|OFF      

(显示CPU时间)

.vfsname ?AUX?   

(显示 VFS 栈信息)

.restore ?DB? FILE 

(从文件中还原数据到表,  默认表为 main)
sqlite>

六.改变输出格式(.mode)

    sqlite3程序能够以八种不一样的格式显示一个查询的结果:"csv", "列", "html", "插入", "行", "制表"和"tcl"。你能够用".mode"点命令在这些输出格式之间切换。
    默认的输出格式是“列表”。在列表模式下,每条查询结果记录被写在一行中而且每列之间以一个字符串分割符隔开。默认的分隔符是一个管道符号(“|”)。列表符号在当你输出查询结果到另一个符加处理的程序(如AWK)中去是尤其有用。
sqlite> .mode list
sqlite> select * from tbl1;
hello|10
goodbye|20
sqlite>
    你能够用“.separator”点命令来改变分界符。例如,为了把分割符改成一个逗号和一个空格,你能够这样作:
sqlite> .separator ", "
sqlite> select * from tbl1;
hello, 10
goodbye, 20
sqlite>
    在“line"模式下,每个位于条记录中的列在它本身那行显示。每行由列名、一个等号和列数据组成。下一条记录以一个空行隔开。这是一个行模式输出的例子:
sqlite> .mode line
sqlite> select * from tbl1;
one = hello
two = 10
one = goodbye
two = 20
sqlite>
    在列模式下,每条记录在一个单独的行中以数据列对齐的方式显示。列如:
sqlite> .mode column
sqlite> select * from tbl1;
one          two       
----------   ----------
hello        10        
goodbye      20        
sqlite>
        在默认的状况下,每列至少10个字符宽。太宽(超过设定的宽度)的数据将被截取。你能够用“.width”命令来调整列宽。以下所示:
sqlite> .width 12 6            (第一列12,第二列6)
sqlite> select * from tbl1;
one            two   
------------   ------
hello          10    
goodbye        20    
sqlite>
     上面例子中".width"命令设置第一列宽为12第二列宽为6。其它的列宽不变。你能够指定与你查询结果须要的列数同样多的“.width”参数。
    若是你指定一列宽为0,那么这个列宽将自动如下面三个数字中的最大值作为列宽:十、表头宽度和最宽的数据列的宽度。这可让列自动调整宽度。每列的默认设置为自动调整的0值。
    出如今输出开头两行的列标示能够用".header"点命令关闭。在上面的例子中,列标示是打开的。能够用下面的方法关闭列标示:
sqlite> .header off
sqlite> select * from tbl1;
hello          10    
goodbye        20    
sqlite>
    另一个有用的输出模式是"insert"。在插入模式下,被子格式化为看起来像SQL INSERT语句的样式。你能够用插入模式来产生文件(便于)之后用于不一样数据库的输入。
    当指定插入模式时,你必须给定一个特定参数就是要插入的表名。例如:
sqlite> .mode insert new_table
sqlite> select * from tbl1;
INSERT INTO 'new_table' VALUES('hello',10);
INSERT INTO 'new_table' VALUES('goodbye',20);
sqlite>
    最新的输出格式是“html”。在这种模式下,sqlite3把查询的结果写作XHTML表。开始的<TABLE>和结束 的</TABLE>(标记)没有写出,但有<TR>、<TH>和<TD>等分界符。html输出对 CGI来讲是至关有用地。
把结果写到文件中

七.查询数据库结构

     sqlite3程序提供几个有用的用于查询数据库结构的快捷命令。这些不是不能够用别的方式来实现。这些命令仅仅是一个快捷方式而已。
    例如,为了查看数据库的表列表,你能够敲入“.tables”。
sqlite> .tables
tbl1
tbl2
sqlite>
    “.tables”命令类似于设置列表模式而后执行接下来的查询:
SELECT name FROM sqlite_master WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%'UNION ALL SELECT name FROM sqlite_temp_master WHERE type IN ('table','view') ORDER BY 1sqlite> .schema
create table tbl1(one varchar(10), two smallint)
CREATE TABLE tbl2 (
  f1 varchar(30) primary key,
   f2 text,
   f3 real
)
sqlite> .schema tbl2
CREATE TABLE tbl2 (
   f1 varchar(30) primary key,
   f2 text,
   f3 real
)
sqlite>

八.事实上

你能够查看sqlite3的源代码(能够在源文件树的src/shell.c中),你可找到上面的具体的查询。
“.indices” 命令做用相似的方式是列出特定表的全部的索引。“.indics”命令须一个参数即所要索引表的表名。最后,但不是至少,是“.schema”命令。不带 任何参数,“.schema”命令显示原始的用于建立当前数据库的CREATE TABLE和CREATE INDEX语句。若是你给".schema"命令一个表名,它显示原始的建立该表和它全部索引的CREATE语句。咱们能够:
".schema"命令能够用设置列表而后执行如下查询来实现:
SELECT sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master)WHERE type!='meta'ORDER BY tbl_name, type DESC, name
或者,若是你给".schema"命令一个参数,因为你只想获得一个表的结构,查询能够是这样:
SELECT sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master)WHERE type!='meta' AND sql NOT NULL AND name NOT LIKE 'sqlite_%'ORDER BY substr(type,2,1), name
你能够担供一个参数给.schema命令。若是这橛,查询能够是这样的:
SELECT sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master)WHERE tbl_name LIKE '%s' AND type!='meta' AND sql NOT NULL AND name NOT LIKE 'sqlite_%'ORDER BY substr(type,2,1), name
在查询中“%S“为你的参数所取代。这使你能够询数据库结构的某个子集。
sqlite> .schema %abc%
与这些一块儿,“.table”命令也接受一个模式做为他的参数。若是你给“.table”一个参数,“%”将被先后扩展而且一个LIKE子句被附加到查询上。这让你能够列出只与特定模式相匹配的的表。
“.databases” 命令显示全部当前链接打开的数据库的一个列表。将容许一次到少两个。第一个是“main”,最初打开的那个数据库。第二个是"temp",用于临时表的数 据库。对于用ATTACH语句附加的数据也许有附加数据库列表。输出的第一列与之相联的数据库名,第二列是外部文件名。
sqlite> .databases

九.将整个数据库转换为ASCII文本文件

".dump"命令成一个单一的ASCII文本文件。这个文件能够被用做管道传递给sqlite3命令来转换回数据库。
一个最好的制做一个数据库档案拷贝的命令是:
$ echo '.dump' | sqlite3 ex1 | gzip -c >ex1.dump.gz
它产生一个一个名为ex1.dump.gz的文件,它包含了你之后或在其它机器上重构数据库的全部的信息。要重构数据库,只须敲入:
$ zcat ex1.dump.gz | sqlite3 ex2
这个文本格式是纯粹的SQL语句因此你能够用.dump命令来导出一个SQLite数据库到另外一个经常使用的SQL数据库引擎。好比:
$ createdb ex2
$ sqlite3 ex1 .dump | psql ex2

十.Sqlite3 表结构和数据的导出及导入

数据库结构导出和导入:

“.output” 默认状况下,sqlte3把结送到标准输出。你能够用“.output”命令改变它。只须把输出文件名作为.output命令的输出参数而后全部后续查询结果将被写到那个文件中。

用“.output stdout”再一次改成标准输出。例如:

所有导出
$sqlite3 data.db
sqlite >.output dd
sqlite >.dump

sqlite > .exit

$cat dd               //如下是数据库的结构

PRAGMA foreign_keys=OFF;

BEGIN TRANSACTION;

CREATE TABLE long(h,m);

INSERT INTO "long" VALUES('hhhhhh',2);

INSERT INTO "long" VALUES('hello',2);

INSERT INTO "long" VALUES('mall',5);

INSERT INTO "long" VALUES('suinvzi',8);

INSERT INTO "long" VALUES('meimei',5);

CREATE TABLE bak(m varchar(10), n int);

INSERT INTO "bak" VALUES('hhhhhh',2);

INSERT INTO "bak" VALUES('hell',2);

INSERT INTO "bak" VALUES('mall',5);

INSERT INTO "bak" VALUES('suinvzi',8);

INSERT INTO "bak" VALUES('meimei',5);

COMMIT;

[h2] 导出表结构

sqlite >.output dd

sqlite >.schema

sqlite > .exit

$cat dd       //如下是表的结构

CREATE TABLE bak(m varchar(10), n int);

CREATE TABLE long(h,m);

所有导入 : (用.read命令,执行 FILENAME 中的 SQL语句)
sqlite3 mydb.db
sqlite >.read dd

sqlite >.tables

bak long          //导入的是空表bak,long

数据的导出和导入:

导出:例如:

$sqlite3 data.db
sqlite> .mode list
sqlite> .separator |
sqlite> .output test_file_1
sqlite> select * from long;
sqlite> .exit
$ cat test_file_1
hhhhhh|2

hello|2

mall|5

suinvzi|8

meimei|5
$

备注:每次导出若为同一个文本,则正在导出的内容覆盖上次导出的内容

导入: 例如:(用.import 导入的文本 被导入的表 命令, 把文件中的数据导入表中)

$sqlite3 mydb.db

sqlite> .show

     echo: off

   explain: off

  headers: off

    mode: list

nullvalue: ""

   output: stdout

separator: "|"

     stats: off

     width:
sqlite> .import test_file_1 long
sqlite> select * from long;
hhhhhh|2

hello|2

mall|5

suinvzi|8

meimei|5
导入结束

备注:文本的内容所对应的数据分布与所要导入的表一致,元素间的分割符要与”.show”中separator: "|"的字符一致若是不一致可直接修改, 好比: sqlite>.separator "," 将分隔符转为逗号,否则导入会出错.

十一.其它的点命令

".explain" 命令能够被用来设置输出格式为“column” 并设置列宽为EXPLAIN命令看起来比较合理的宽度。EXPLAIN命令是SQLite特有的SQL扩展,它是对调试有用。若是任何常规的SQL被 EXPLAIN执行,那么SQL命令被分解并分析但并不执行。取而代之的是,虚拟机指令序列将被用于执行SQL命令并返回一个相似的查询结果。如:
sqlite> .explain
sqlite> explain delete from tbl1 where two<20;
addr   opcode         p1      p2      p3          
----   ------------   -----   -----   -------------------------------------   
0      ListOpen       0       0                  
1      Open           0       1       tbl1        
2      Next           0       9                  
3      Field          0       1                  
4      Integer        20      0                  
5      Ge             0       2                  
6      Key            0       0                  
7      ListWrite      0       0                  
8      Goto           0       2                  
9      Noop           0       0                  
10     ListRewind     0       0                  
11     ListRead       0       14                 
12     Delete         0       0                  
13     Goto           0       11                 
14     ListClose      0       0
“.timeout”命令设置sqlite3等待一个试图存储文件锁定请除直到错误返回的总时间。默认的超时值是0所以若是任何须要的数据库表或序列列被锁定时它将当即返回一个错误。
最后,咱们提到“.exit”命令它将致使sqlite3退出。

十二.在命令和脚本中使用sqlite3

一 个在脚本命令中使用sqlite3的方式是用“echo”或“cat”来产生一个命令序列在一个文件中,而后当从一个产生的命令行中重定向输入时调用 sqlite3。它有用而且适应许多环境。但做为一附加的便利是,sqlite3容许一个单一的SQL语句在命令行中做为数据库名后的第二个参数输入。当 sqlite3程序带着两个参数启动时,第二个参数被传递给SQLite库处理,查询以列表模式打印到标准输出,而后程序退出。这个机制被设计用于让 sqlite3容易于用于链接诸如"AWK"的程序。例如:
$ sqlite3 ex1 'select * from tbl1' |
> awk '{printf "<tr><td>%s<td>%s\n",$1,$2 }'
<tr><td>hello<td>10
<tr><td>goodbye<td>20
$

十三.结束命令行命令

SQLite 命令一般以一个分号结束。在一个命令行中你也能够用“GO”单词(大小写敏感)或者一个“/”斜线在它所在好行结束一个命令。这常被SQL Server和Oracle使用。这些将不在sqlite3_exec()中有用,由于命令行在传递它们到函数以前把这些翻译为分号。

十四.参数化的SQL语句

sqlite能够在shell/dos command底下直接执行命令:

对数据库进行SQL操做:
sqlite3数据库 "SQL语句 或 .命令;"

输出 HTML 表格:
sqlite3 -html film.db "select * from film;"

将数据库「导出来」:
sqlite3 film.db ".dump" > output.sql
利用输出的资料,创建一个如出一辙的数据库(加上以上指令,就是标准的SQL数据库备份了):

将数据库「导进去」:
sqlite3 film.db < output.sql
在大量插入资料时,你可能会须要先打这个指令:
begin;
插入完资料后要记得打这个指令,资料才会写进数据库中:
commit;

十五.SQLITE深刻------常见问题

1.如何创建自动增加字段?

简短回答:声明为 INTEGER PRIMARY KEY 的列将会自动增加 。

(若是是最大可能的主键 9223372036854775807,那个,将键值将是随机未使用的数。)如,有下列表:

CREATE TABLE t1(
a INTEGER PRIMARY KEY,
b INTEGER
);
在该表上,下列语句

INSERT INTO t1 VALUES(NULL,123);
在逻辑上等价于:

INSERT INTO t1 VALUES((SELECT max(a) FROM t1)+1,123);
有一个新的API叫作 sqlite3_last_insert_rowid(), 它将返回最近插入的整数值。 注意该整数会比表中该列上的插入以前的最大值大1。 该键值在当前的表中是惟一的。但有可能与已从表中删除的值重叠。要想创建在整个表的生命周期中惟一的键值,须要在 INTEGER PRIMARY KEY 上增长AUTOINCREMENT声明。那么,新的键值将会比该表中曾能存在过的最大值大1。若是最大可能的整数值在数据表中曾经存在过,INSERT将会失败, 并返回SQLITE_FULL错误代码。

2.多个应用程序或一个应用程序的多个实例能够同时访问同一个数据库文件吗?

多个进程可同时打开同一个数据库。多个进程能够同时进行SELECT 操做,但在任一时刻,只能有一个进程对数据库进行更改。

SQLite使用读、写锁控制对数据库的访问。(在Win95/98/ME等不支持读、写锁的系统下,使用一个几率性的模拟来代替。)但使用时要注意:若是数据库文件存放于一个NFS文件系统上,这种锁机制可能不能正常工做。 这是由于 fcntl() 文件锁在不少NFS上没有正确的实现。 在可能有多个进程同时访问数据库的时候,应该避免将数据库文件放到NFS上。在Windows上,Microsoft的文档中说:若是使用 FAT 文件系统而没有运行 share.exe 守护进程,那么锁多是不能正常使用的。那些在Windows上有不少经验的人告诉我:对于网络文件,文件锁的实现有好多Bug,是靠不住的。若是他们说的是对的,那么在两台或多台Windows机器间共享数据库可能会引发不指望的问题。

咱们意识到,没有其它嵌入式的 SQL 数据库引擎能象 SQLite 这样处理如此多的并发。SQLite容许多个进程同时打开一个数据库,同时读一个数据库。当有任何进程想要写时,它必须在更新过程当中锁住数据库文件。但那一般只是几毫秒的时间。其它进程只需等待写进程干完活结束。典型地,其它嵌入式的SQL数据库引擎同时只容许一个进程链接到数据库。

可是,Client/Server数据库引擎(如 PostgreSQL, MySQL, 或 Oracle)一般支持更高级别的并发,而且容许多个进程同时写同一个数据库。这种机制在Client/Server结构的数据库上是可能的,由于老是有一个单一的服务器进程很好地控制、协调对数据库的访问。若是你的应用程序须要不少的并发,那么你应该考虑使用一个Client/Server 结构的数据库。但经验代表,不少应用程序须要的并发,每每比其设计者所想象的少得多。

当SQLite试图访问一个被其它进程锁住的文件时,缺省的行为是返回 SQLITE_BUSY。 能够在C代码中使用 sqlite3_busy_handler() 或 sqlite3_busy_timeout() API 函数调整这一行为。

3.在SQLite数据库中如何列出全部的表和索引?

若是你运行 sqlite3 命令行来访问你的数据库,能够键入 “.tables”来得到全部表的列表。或者,你能够输入 “.schema” 来看整个数据库模式,包括全部的表的索引。输入这些命令,后面跟一个LIKE模式匹配能够限制显示的表。

在一个 C/C++ 程序中(或者脚本语言使用 Tcl/Ruby/Perl/Python 等) 你能够在一个特殊的名叫 SQLITE_MASTER 上执行一个SELECT查询以得到全部 表的索引。每个 SQLite 数据库都有一个叫 SQLITE_MASTER 的表, 它定义数据库的模式。 SQLITE_MASTER 表看起来以下:

CREATE TABLE sqlite_master (
type TEXT,
name TEXT,
tbl_name TEXT,
rootpage INTEGER,
sql TEXT
);
对于表来讲,type 字段永远是 'table',name 字段永远是表的名字。因此,要得到数据库中全部表的列表,使用下列SELECT语句:

SELECT name FROM sqlite_master
WHERE type='table'
ORDER BY name;
对于索引,type 等于 'index', name 则是索引的名字,tbl_name 是该索引所属的表的名字。无论是表仍是索引,sql 字段是原先用 CREATE TABLE 或 CREATE INDEX 语句建立它们时的命令文本。对于自动建立的索引(用来实现 PRIMARY KEY 或 UNIQUE 约束),sql字段为NULL。

SQLITE_MASTER 表是只读的。不能对它使用 UPDATE、INSERT 或 DELETE。 它会被 CREATE TABLE、CREATE INDEX、DROP TABLE 和 DROP INDEX 命令自动更新。

临时表不会出如今 SQLITE_MASTER 表中。临时表及其索引和触发器存放在另一个叫 SQLITE_TEMP_MASTER 的表中。SQLITE_TEMP_MASTER 跟 SQLITE_MASTER 差很少,但它只是对于建立那些临时表的应用可见。若是要得到全部表的列表, 无论是永久的仍是临时的,可使用相似下面的命令:

SELECT name FROM
   (SELECT * FROM sqlite_master UNION ALL
    SELECT * FROM sqlite_temp_master)
WHERE type='table'
ORDER BY name

4.在SQLite中,VARCHAR字段最长是多少?

SQLite 不强制 VARCHAR 的长度。 你能够在 SQLITE 中声明一个 VARCHAR(10),SQLite仍是能够很高兴地容许你放入500个字符。 而且这500个字符是原封不动的,它永远不会被截断。

5.SQLite支持二进制大对象吗?

SQLite 3.0 及之后版本容许你在任何列中存储 BLOB 数据。即便该列被声明为其它类型也能够。

在SQLite中,如何在一个表上添加或删除一列?

SQLite 有有限地 ALTER TABLE 支持。你可使用它来在表的末尾增长一列,可更改表的名称。若是须要对表结构作更复杂的改变,则必须从新建表。重建时能够先将已存在的数据放到一个临时表中,删除原表, 建立新表,而后将数据从临时表中复制回来。

如,假设有一个 t1 表,其中有 "a", "b", "c" 三列, 若是要删除列 c ,如下过程描述如何作:

BEGIN TRANSACTION;
CREATE TEMPORARY TABLE t1_backup(a,b);
INSERT INTO t1_backup SELECT a,b FROM t1;
DROP TABLE t1;
CREATE TABLE t1(a,b);
INSERT INTO t1 SELECT a,b FROM t1_backup;
DROP TABLE t1_backup;
COMMIT;[h3] 

6.在数据库中删除了不少数据,但数据库文件没有变小,是Bug吗?

不是。当你从SQLite数据库中删除数据时, 未用的磁盘空间将会加入一个内部的“自由列表”中。 当你下次插入数据时,这部分空间能够重用。磁盘空间不会丢失,但也不会返还给操做系统。

若是删除了大量数据,而又想缩小数据库文件占用的空间,执行 VACUUM 命令。 VACUUM 将会从头从新组织数据库。这将会使用数据库有一个空的“自由链表”, 数据库文件也会最小。但要注意的是,VACUUM 的执行会须要一些时间(在SQLite开发时,在Linux上,大约每M字节须要半秒种),而且, 执行过程当中须要原数据库文件至多两倍的临时磁盘空间。

对于 SQLite 3.1版本,一个 auto-vacumm 模式能够替代 VACUUM 命令。 可使用 auto_vacuum pragma 打开。

7.SQLITE_SCHEMA error是什么错误?为何会出现该错误?

当一个准备好的(prepared)SQL语句再也不有效或者没法执行时,将返回一个 SQLITE_SCHEMA 错误。发生该错误时,SQL语句必须使用 sqlite3_prepare() API来从新编译. 在 SQLite 3 中, 一个 SQLITE_SCHEMA 错误只会发生在用 sqlite3_prepare()/sqlite3_step()/sqlite3_finalize() API 执行 SQL 时。而不会发生在使用 sqlite3_exec()时。 在版本2中不是这样。

准备好的语句失效的最一般缘由是:在语句准备好后, 数据库的模式又被修改了。另外的缘由会发生在:

数据库离线:DETACHed.
数据库被 VACUUMed
一个用户存储过程定义被删除或改变。
一个 collation 序列定义被删除或改变。
认证函数被改变。
在全部状况下,解决方法是从新编译并执行该SQL语句。 由于一个已准备好的语句能够因为其它进程改变数据库模式而失效,全部使用 sqlite3_prepare()/sqlite3_step()/sqlite3_finalize() API 的代码都应准备处理 SQLITE_SCHEMA 错误。下面给出一个例子:

    int rc;
    sqlite3_stmt *pStmt;
    char zSql[] = "SELECT .....";

    do {
      /* Compile the statement from SQL. Assume success. */
      sqlite3_prepare(pDb, zSql, -1, &pStmt, 0);

      while( SQLITE_ROW==sqlite3_step(pStmt) ){
        /* Do something with the row of available data */
      }

      /* Finalize the statement. If an SQLITE_SCHEMA error has
      ** occured, then the above call to sqlite3_step() will have
      ** returned SQLITE_ERROR. sqlite3_finalize() will return
      ** SQLITE_SCHEMA. In this case the loop will execute again.
      */
      rc = sqlite3_finalize(pStmt);
    } while( rc==SQLITE_SCHEMA );

8.如何一次插入多个数据

Insert into SAMPLE(PRJNUM, PRJNAME, EMYNUM, EMYNAME, SALCATEGORY, SALPACKAGE)

values(100001, 'TPMS', 200001, 'Johnson', 'A', 2000), (100001, 'TPMS', 200002,

'Christine', 'B', 3000), (100001, 'TPMS', 200003, 'Kevin', 'C', 4000), (100002,

'TCT', 200001, 'Johnson', 'A', 2000), (100002, 'TCT', 200004, 'Apple', 'B',

3000);

9.如何备份数据库

先打开数据库test.db

sqlite>sqlite3 test.db

sqlite> .backup test.bak

10.如何恢复数据库

先打开数据库test.db

sqlite>sqlite3 test.db

sqlite> .restore test.bak

11.先判断表若是不存在,则再建立表

SQL能够以下写,供参考:

create table if not exists student(id integer primary key autoincrement,/

age smallint ,anchor smallint);

12.如何查询SQLite3小工具的版本

执行 select sqlite_version();命令便可

十六.Sqlite数据库中索引的使用、索引的优缺点

要使用索引对数据库的数据操做进行优化,那必须明确几个问题:
1.什么是索引
2.索引的原理
3.索引的优缺点
4.何时须要使用索引,如何使用
围绕这几个问题,来探究索引在数据库操做中所起到的做用。

1.        数据库索引简介


回忆一下小时候查字典的步骤,索引和字典目录的概念是一致的。字典目录可让咱们不用翻整本字典就找到咱们须要的内容页数,而后翻到那一页就能够。索引也是同样,索引是对记录按照多个字段进行排序的一种展示。对表中的某个字段创建索引会建立另外一种数据结构,其中保存着字段的值,每一个值还包括指向与它相关记录的指针。这样,就没必要要查询整个数据库,天然提高了查询效率。同时,索引的数据结构是通过排序的,于是能够对其执行二分查找,那就更快了。

2. B-树与索引

大多数的数据库都是以B-树或者B+树做为存储结构的,B树索引也是最多见的索引。先简单介绍下B-树,能够加强对索引的理解。
B-树是为磁盘设计的一种多叉平衡树,B树的真正最准确的定义为:一棵含有t(t>=2)个关键字的平衡多路查找树。一棵M阶的B树知足如下条件:
1)每一个结点至多有M个孩子;
2)除根结点和叶结点外,其它每一个结点至少有M/2个孩子;
3)根结点至少有两个孩子(除非该树仅包含一个结点);
4)全部叶结点在同一层,叶结点不包含任何关键字信息,能够看做一种外部节点;
5)有K个关键字的非叶结点刚好包含K+1个孩子;
 B树中的每一个结点根据实际状况能够包含大量的关键字信息和分支(固然是不能超过磁盘块的大小,根据磁盘驱动(disk drives)的不一样,通常块的大小在1k~4k左右);这样树的深度下降了,这就意味着查找一个元素只要不多结点从外存磁盘中读入内存,很快访问到要查找的数据。B-树上操做的时间一般由存取磁盘的时间和CPU计算时间这两部分构成。而相对于磁盘的io速度,cpu的计算时间能够忽略不计,因此B树的意义就显现出来了,树的深度下降,而深度决定了io的读写次数。
B树索引是一个典型的树结构,其包含的组件主要是:
1)叶子节点(Leaf node):包含条目直接指向表里的数据行。
2)分支节点(Branch node):包含的条目指向索引里其余的分支节点或者是叶子节点。
3)  根节点(Root node):一个B树索引只有一个根节点,它实际就是位于树的最顶端的分支节点。
以下图所示:




 
每一个索引都包含两部份内容,一部分是索引自己的值,第二部分即指向数据页或者另外一个索引也的指针。每一个节点即为一个索引页,包含了多个索引。
当你为一个空表创建一个索引,数据库会分配一个空的索引页,这个索引页即表明根节点,在你插入数据以前,这个索引页都是空的。每当你插入数据,数据库就会在根节点建立索引条目,。当根节点插满的时候,再插入数据时,根节点就会分裂。举个例子,根节点插入了如图所示的数据。(超过4个就分裂),这时候插入H,就会分裂成2个节点,移动G到新的根节点,把H和N放在新的右孩子节点中。如图所示:
    
    根节点插满4个节点
    
      插入H,进行分裂。


大体的分裂步骤以下:
1)建立两个儿子节点
2)将原节点中的数据近似分为两半,写入两个新的孩子节点中。
3)在跟节点中放置指向页节点的指针

当你不断向表中插入数据,根节点中指向叶节点的指针也被插满,当叶子还须要分裂的时候,根节点没有空间再建立指向新的叶节点的指针。那么数据库就会建立分支节点。随着叶子节点的分裂,根节点中的指针都指向了这些分支节点。随着数据的不断插入,索引会增长更多的分支节点,使树结构变成这样的一个多级结构。

3. 索引的种类

1)汇集索引:表中行的物理顺序与键值的逻辑(索引)顺序相同。由于数据的物理顺序只能有一种,因此一张表只能有一个汇集索引。若是一张表没有汇集索引,那么这张表就没有顺序的概念,全部的新行都会插入到表的末尾。对于汇集索引,叶节点即存储了数据行,再也不有单独的数据页。就好比说我小时候查字典历来不看目录,我以为字典自己就是一个目录,好比查裴字,只须要翻到p字母开头的,再按顺序找到e。经过这个方法我每次都能最快的查到老师说的那个字,获得老师的表扬。

2)非汇集索引:表中行的物理顺序与索引顺序无关。对于非汇集索引,叶节点存储了索引字段值以及指向相应数据页的指针。叶节点紧邻在数据之上,对数据页的每一行都有相应的索引行与之对应。有时候查字典,我并不知道这个字读什么,那我就不得不经过字典目录的“部首”来查找了。这时候我会发现,目录中的排序和实际正文的排序是不同的,这对我来讲很苦恼,由于我不能比别人快了,我须要先再目录中找到这个字,再根据页数去找到正文中的字。 

4.索引与数据的查询,插入与删除

1)查询。查询操做就和查字典是同样的。当咱们去查找指定记录时,数据库会先查找根节点,将待查数据与根节点的数据进行比较,再经过根节点的指针查询下一个记录,直到找到这个记录。这是一个简单的平衡树的二分搜索的过程,我就不赘述了。在汇集索引中,找到页节点即找到了数据行,而在非汇集索引中,咱们还须要再去读取数据页。

2)插入。汇集索引的插入操做比较复杂,最简单的状况,插入操做会找到对于的数据页,而后为新数据腾出空间,执行插入操做。若是该数据页已经没有空间,那就须要拆分数据页,这是一个很是耗费资源的操做。对于仅有非汇集索引的表,插入只需在表的末尾插入便可。若是也包含了汇集索引,那么也会执行汇集索引须要的插入操做。

3)删除。删除行后下方的数据会向上移动以填补空缺。若是删除的数据是该数据页的最后一行,那么这个数据页会被回收,它的先后一页的指针会被改变,被回收的数据页也会在特定的状况被从新使用。与此同时,对于汇集索引,若是索引页只剩一条记录,那么该记录可能会移动到邻近的索引表中,原来的索引页也会被回收。而非汇集索引没办法作到这一点,这就会致使出现多个数据页都只有少许数据的状况。

5. 索引的优缺点

其实经过前面的介绍,索引的优缺点已经一目了然。
先说优势:
    1)大大加快数据的检索速度,这也是建立索引的最主要的缘由
    2)加速表和表之间的链接,特别是在实现数据的参考完整性方面特别有意义。

    3)在使用分组和排序子句进行数据检索时,一样能够显著减小查询中分组和排序的时间。

   再说缺点:
  1)建立索引须要耗费必定的时间,可是问题不大,通常索引只要build一次
  2)索引须要占用物理空间,特别是汇集索引,须要较大的空间

  3)当对表中的数据进行增长、删除和修改的时候,索引也要动态的维护,下降了数据的维护速度,这个是比较大的问题。

6. 索引的使用

 根据上文的分析,咱们大体对何时使用索引有了本身的想法(若是你没有,回头再看一遍。。。)。通常咱们须要在这些列上创建索引:
1)在常常须要搜索的列上,这是毋庸置疑的; 
2)常常同时对多列进行查询,且每列都含有重复值能够创建组合索引,组合索引尽可能要使经常使用查询造成索引覆盖(查询中包含的所需字段皆包含于一个索引中,咱们只须要搜索索引页便可完成查询)。 同时,该组合索引的前导列必定要是使用最频繁的列。对于前导列的问题,在后面sqlite的索引使用介绍中还会作讨论。
3)在常常用在链接的列上,这些列主要是一些外键,能够加快链接的速度,链接条件要充分考虑带有索引的表。; 

4)在常常须要对范围进行搜索的列上建立索引,由于索引已经排序,其指定的范围是连续的,一样,在常常须要排序的列上最好也建立索引。

6)在常常放到where子句中的列上面建立索引,加快条件的判断速度。要注意的是where字句中对列的任何操做(如计算表达式,函数)都须要对表进行整表搜索,而没有使用该列的索引。因此查询时尽可能把操做移到等号右边。

对于如下的列咱们不该该建立索引:
1)不多在查询中使用的列
2)含有不多非重复数据值的列,好比只有0,1,这时候扫描整表一般会更有效
3)对于定义为TEXT,IMAGE的数据不该该建立索引。这些字段长度不固定,或许很长,或许为空。
固然,对于更新操做远大于查询操做时,不创建索引。也能够考虑在大规模的更新操做前drop索引,以后从新建立,不过这就须要把建立索引对资源的消耗考虑在内。总之,使用索引须要平衡投入与产出,找到一个产出最好的点。

7. 在sqlite中使用索引 

1)Sqlite不支持汇集索引,android默认须要一个_id字段,这保证了你插入的数据会按“_id”的整数顺序插入,这个integer类型的主键就会扮演和汇集索引同样的角色。因此不要再在对于声明为:INTEGER PRIMARY KEY的主键上建立索引。

2)不少对索引不熟悉的朋友在表中建立了索引,却发现没有生效,其实这大多数和我接下来说的有关。对于where子句中出现的列要想索引生效,会有一些限制,这就和前导列有关。所谓前导列,就是在建立复合索引语句的第一列或者连续的多列。好比经过:CREATE INDEX comp_ind ON table1(x, y, z)建立索引,那么x,xy,xyz都是前导列,而yz,y,z这样的就不是。下面讲的这些,对于其余数据库或许会有一些小的差异,这里以sqlite为标准。在where子句中,前导列必须使用等于或者in操做,最右边的列可使用不等式,这样索引才能够彻底生效。同时,where子句中的列不须要全创建了索引,可是必须保证创建索引的列之间没有间隙。举几个例子来看吧:

用以下语句建立索引:
CREATE INDEX idx_ex1 ON ex1(a,b,c,d,e,...,y,z);
这里是一个查询语句:
...WHERE a=5 AND b IN (1,2,3) AND c IS NULL AND d='hello'
这显然对于abcd四列都是有效的,由于只有等于和in操做,而且是前导列。
再看一个查询语句:
... WHERE a=5 AND b IN (1,2,3) AND c>12 AND d='hello'
那这里只有a,b和c的索引会是有效的,d列的索引会失效,由于它在c列的右边,而c列使用了不等式,根据使用不等式的限制,c列已经属于最右边。
最后再看一条:
... WHERE b IN (1,2,3) AND c NOT NULL AND d='hello'

索引将不会被使用,由于没有使用前导列,这个查询会是一个全表查询。

3)对于between,or,like,都没法使用索引。
如 ...WHERE myfield BETWEEN 10 and 20;
这时就应该将其转换成:
    ...WHERE myfield >= 10 AND myfield <= 20;
再如LIKE:...mytable WHERE myfield LIKE 'sql%';;
此时应该将它转换成:
...WHERE myfield >= 'sql' AND myfield < 'sqm';
    再如OR:...WHERE myfield = 'abc' OR myfield = 'xyz';
此时应该将它转换成:
...WHERE myfield IN ('abc', 'xyz');

其实除了索引,对查询性能的影响因素还有不少,好比表的链接,是否排序等。影响数据库操做的总体性能就须要考虑更多因素,使用更对的技巧,不得不说这是一个很大的学问。

最后在android上使用sqlite写一个简单的例子,看下索引对数据库操做的影响。
建立以下表和索引:
   db.execSQL("create table if not exists t1(a,b)");        
   db.execSQL("create index if not exists ia on t1(a,b)");
插入10万条数据,分别对表进行以下操做:
select * from t1 where a='90012'
插入:insert into t1(a,b) values('10008','name1.6982235534984673')
更新:update t1 set b='name1.999999' where a = '887'

删除:delete from t1 where a = '1010'

数据以下(5次不一样的操做取平均值):
操做   无索引    有索引
查询   170ms  5ms
插入   65ms   75ms
更新   240ms  52ms
删除   234ms  78ms

        能够看到显著提高了查询的速度,稍稍减慢了插入速度,还稍稍提高了更新数据和删除数据的速度。若是把更新和删除中的where子句中的列换成b,速度就和没有索引同样了,由于索引失效。因此索引能大幅度提高查询速度,对于删除和更新操做,若是where子句中的列使用了索引,即便须要从新build索引,有可能速度仍是比不使用索引要快的。对与插入操做,索引显然是个负担。同时,索引让db的大小增长了2倍多。

       还有个要吐槽的是,android中的rawQurey方法,执行完sql语句后返回一个cursor,其实并无完成一个查询操做,我在rawquery以前和以后计算查询时间,永远是1ms...这让我无比苦闷。看了下源码,在对cursor调用moveToNext这些移动游标方法时,都会最终先调用getCount方法,而getCount方法才会调用native方法调用真正的查询操做。这种设计显然更加合理


 [h1]事物…

 [h2]这是一个事物操做的范例:

 [h3]事物..

相关文章
相关标签/搜索