当前位置:文档之家› SQLite3源程序分析

SQLite3源程序分析

SQLite3源程序分析
SQLite3源程序分析

SQLite3源程序分析

作者:空转

本文分析的SQLite版本为3.6.18。现在已经变成3.6.20了,但本文中所涉及的内容变化不大。读者最好能下载一个源程序,然后将本文与源程序对照阅读。这样也有利于发现本文的错误,说实话吧,我写的时候是连分析带猜的,错误肯定很多。

参考文献:

1-The Definitive Guide to SQLite . Michael Owens:比较经典的SQLite著作。我边看边翻译了其中的部分内容,但翻得不好,大家还是看原文吧。

2-SQLite文件格式分析_v102 . 空转:我写的,写得特好。现在是v102版,跟前面的版本相比增加了不少背景知识,对文件格式的介绍算是很全面了。看本文之前,应该先浏览一下此参考文献。

1.SQLite3程序分析

1.1. 主程序流程

所谓“主程序”是指SQLite所提供的命令行处理程序(CLP)。通过对它的分析可以对SQLite 源程序建立整体概念,比一上来就直接分析单独API的处理过程要容易。CLP的主要程序都在shell.c中。

CLP的执行流程很简单:循环接受用户输入的SQL命令,处理SQL命令。命令的执行都是调用sqlite3_exec()函数完成,也就是采用的是“执行封装的Query”的形式[1]。

程序定义了一个功能比较强大的回叫函数来处理SQL命令执行的返回结果:static int callback(void *pArg, int nArg, char **azArg, char **azCol);

程序定义了9种回显的形式,通过一个callback_data结构来对回显参数进行配置。

1.1.1.程序主函数

程序的main()函数在shell.c的尾部,简化后的main()函数的执行过程主要分为5步:

1.设置回显参数

2.取数据库文件名

3.打开数据库

4.循环处理SQL命令

5.关闭数据库

如下:

int main(int argc, char **argv){

struct callback_data data; //回显参数

int rc = 0;

Argv0 = argv[0];

main_init(&data); //设置默认的回显形式

//取数据库文件名,如没有,默认为内存数据库

data.zDbFilename = argv[1];

data.out = stdout;

/* 如果数据库文件存在,则打开它。

** 如果不存在,先不打开(现在什么都不做),

** 可以防止用户因错误的输入而创建空文件。

*/

if( access(data.zDbFilename, 0)==0 ){

open_db(&data);

}

printf(

"SQLite version %s\n"

"Enter \".help\" for instructions\n"

"Enter SQL statements terminated with a \";\"\n",

sqlite3_libversion()

);

rc = process_input(&data, 0);

if( db ){ //关闭数据库

if( sqlite3_close(db)!=SQLITE_OK ){

fprintf(stderr,"error closing database: %s\n", sqlite3_errmsg(db));

}

}

return rc;

}

说明:上述函数与源程序相比做了很大的简化,去掉的部分不是不重要的,而是“可以不解释”的。实用程序的流程一般都是复杂的,SQLite也不例外。本文按照自己的主线进行介绍,只求能说明问题(自圆其说),主线之外的东西,不管重不重要,都尽量忽略。后面的函数也存在这样情况,就不再说明了。

回显参数的设置就不再介绍了,参考源程序的callback()函数和callback_data结构,有关回叫函数的使用见参考文献一。下面介绍数据库的打开过程。

1.1.

2.打开数据库

数据库文件的打开过程在SQLite的权威文档中有介绍,过程如下图:

图1-1 数据库文件的打开过程

在CLP中打开数据库,比上图又多了两层,其调用层次如下:

1-main():

位于shell.c。

从命令行参数中得到数据库名,如果数据库文件存在,则打开它。

2-open_db():

位于shell.c。

功能:确认数据库是否已经打开。如果已打开,则什么都不做。如果没有,则打开它。如果打开失败,输出一个错误信息。

3-sqlite3_open():

位于main.c。

功能:打开一个数据库。

该函数中只包含对opendatabase()的调用,但调用的参数与sqlite3_open_v2()所使用的参数不同。

4-opendatabase():

位于main.c。

功能:这个函数为sqlite3_open()和sqlite3_open16()工作,打开一个数据库。数据库文件名"zFilename"采用UTF-8编码。

先生成各类标志什么的,然后生成默认的排序法。当需要生成数据库后台驱动时,调用sqlite3BtreeFactory()。

在此函数中真正分配sqlite结构的空间:db = sqlite3MallocZero( sizeof(sqlite3) )。

在调用sqlite3BtreeFactory()之前,需要对db的一些域进行设置。

5-sqlite3BtreeFactory()

位于main.c。

功能:本函数创建到数据库BTree驱动的连接。如果zFilename是文件名,则打开并使用它。如果zFilename是":memory:",则使用内存数据库(在连接断开时释放)。

如果zFilename为空且数据库是虚拟(virtual)的,则只是暂时使用,在连接断开时被删除。虚拟数据库可以是磁盘文件或就在内存中,由sqlite3TempInMemory()函数来决定是哪一种情况。

6-sqlite3BtreeOpen():

位于btree.c。

功能:打开一个数据库文件。

由于在sqlite3BtreeFactory()中已经调用过sqlite3TempInMemory()函数,所以此处逻辑稍简单了一些。

zFilename是数据库文件名。如果zFilename为空,创建一个具有随机文件名的数据库,这个数据库会在调用sqlite3BtreeClose()时被删除。

如果zFilename是":memory:",创建内存数据库,并在关闭时被释放。

如果此Btree是共享缓冲区的候选者,则尝试寻找一个已存在的BtShared来共享。(参本文后面关于内存数据结构的介绍)

如果不是共享缓冲区的候选者或未找到已存在的BtShared,则调用sqlite3PagerOpen()函数打开文件。

文件打开之后,调用sqlite3PagerReadFileheader()来读文件头中的配置信息。

7-sqlite3PagerOpen():

位于pager.c。

功能:分配并初始化一个新Pager对象,将其指针放到*ppPager。

该pager会在调用sqlite3PagerClose()时被释放。

zFilename参数是要打开的数据库文件的路径。

如果zFilename为空,创建随机文件名的文件。

如果zFilename为":memory:",所有信息都放到缓冲区中,不会被写入磁盘。这用来实现内存数据库。

如果pager对象已分配且指定文件打开成功,返回SQLITE_OK并将*ppPager指向新pager 对象。

如果有错误发生,*ppPager置空并返回错误代码。

执行过程是:先申请空间,再调用sqlite3OsOpen()打开文件(如果需要),再根据打开的文件设置内存。

8-sqlite3OsOpen():

位于os.c。

功能:打开一个文件,与具体的操作系统无关。

是一种VFS封装。VFS的意思是"virtual file system",虚拟文件系统。

本函数只有几条语句,只有一条关键语句:

rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x7f1f, pFlagsOut);

对于Win32操作系统,该语句实际调用的是winOpen()函数。

9-winOpen():

位于os_win.c。

功能:打开一个Windows操作系统文件。

先将文件名转换为操作系统所使用的编码。再设置一系列参数。

最终调用操作系统函数CreateFileA()打开文件。

10-CreateFileA():

位于WINBASE.H。

功能:

打开文件名所指定的文件。如果文件不存在,则创建。

1.1.3.循环处理SQL命令

SQL命令的处理是由process_input()函数完成的。该函数还完成”.”命令的处理,这我们就不管了。简化后的process_input()函数如下:

static int process_input(struct callback_data *p, FILE *in){

while( 1 ){

zLine = one_input_line(zSql, in);

if( zLine && zLine[0]=='.' && nSql==0 ){

rc = do_meta_command(zLine, p);

continue;

}

rc = sqlite3_exec(p->db, zSql, callback, p, &zErrMsg);

if( rc || zErrMsg ){

处理出错信息;

}

}

return errCnt;

}

这么简化应该就不用解释了。

1.2. SQL命令编译与执行的过程

1.2.1.sqlite3_exec()函数

函数sqlite3_exec()位于文件legacy.c的尾部,其函数头为:

int sqlite3_exec(

sqlite3 *db, /* 一个打开的数据库连接 */

const char *zSql, /* 要执行的SQL语句 */

sqlite3_callback xCallback, /* 回叫函数 */

void *pArg, /* 传递给xCallback()的第一个参数 */

char **pzErrMsg /* 将错误信息写到*pzErrMsg中 */

)

sqlite3_exec()函数一次可以执行多条SQL命令。执行完成后返回一个SQLITE_ success/failure 代码,还会将错误信息写到*pzErrMsg中。如果SQL是查询,查询结果中的每一行都会调用xCallback()函数。pArg为传递给xCallback()的第一个参数。如果xCallback==NULL,即使对查询命令也没有回叫调用。

sqlite3_exec()函数的实现体现了一个典型的、实用的SQL语句处理过程,我认为对应用程序的开发很有借鉴意义,所以就不过多简化了,去掉一些测试代码,增加一些注释,源程序基本如下:

int sqlite3_exec(

sqlite3 *db, /* 一个打开的数据库连接 */

const char *zSql, /* 要执行的SQL语句 */

sqlite3_callback xCallback, /* 回叫函数 */

void *pArg, /* 传递给xCallback()的第一个参数 */

char **pzErrMsg /* 将错误信息写到*pzErrMsg中 */

){

int rc = SQLITE_OK; /* 返回码 */

const char *zLeftover; /* 未处理的SQL串尾部。zSql中可能包含多个SQL

语句,一次处理一个,此变量为剩下的还未处理的

语句。 */

sqlite3_stmt *pStmt = 0; /* 当前SQL语句(对象) */

char **azCols = 0; /* 结果字段(s)的名称 */

int nRetry = 0; /* 重试的次数 */

int callbackIsInit; /* 如果初始化了回叫函数,为true */

if( zSql==0 ) zSql = "";

sqlite3Error(db, SQLITE_OK, 0); /* 清除db中的错误信息 */

while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){ int nCol;

char **azVals = 0;

pStmt = 0;

rc = sqlite3_prepare(db, zSql, -1, &pStmt, &zLeftover);/* 编译一条语句 */ if( rc!=SQLITE_OK ){continue;}

if( !pStmt ){

/* 遇到注释时会执行此分支 */

zSql = zLeftover;

continue;

}

callbackIsInit = 0;

nCol = sqlite3_column_count(pStmt); /* 取字段数 */

while( 1 ){

int i;

rc = sqlite3_step(pStmt); /* 执行语句 */

/* 如果有回叫函数并且需要,则调用回叫函数 */

if( xCallback && (SQLITE_ROW==rc ||

(SQLITE_DONE==rc && !callbackIsInit

&& db->flags&SQLITE_NullCallback)) ){ /* 1-如果回叫函数未初始化,则初始化之 */

if( !callbackIsInit ){

/* 此分支只执行一次 */

azCols = sqlite3DbMallocZero(db, 2*nCol*sizeof(const char*) + 1); if( azCols==0 ){

goto exec_out;

}

for(i=0; i

/* 取各字段的名称 */

azCols[i] = (char *)sqlite3_column_name(pStmt, i);

}

callbackIsInit = 1;

}

/* 2-如果返回的是记录 */

if( rc==SQLITE_ROW ){

azVals = &azCols[nCol];

for(i=0; i

/* 取各字段的值 */

azVals[i] = (char *)sqlite3_column_text(pStmt, i);

if( !azVals[i] && sqlite3_column_type(pStmt, i)!=SQLITE_NULL ){ db->mallocFailed = 1;

goto exec_out;

}

}

}

/* 3-调用回叫函数对返回的记录进行处理 */

if( xCallback(pArg, nCol, azVals, azCols) ){

rc = SQLITE_ABORT;

sqlite3VdbeFinalize((Vdbe *)pStmt);

pStmt = 0;

sqlite3Error(db, SQLITE_ABORT, 0);

goto exec_out;

}

}

/*

如果返回的不是记录,有两种情况:一种是到达结果记录集的结尾,

第二种是执行create table一类的不返回记录集的命令。

无论哪种情况,此处都需要“定案”。

*/

if( rc!=SQLITE_ROW ){

rc = sqlite3VdbeFinalize((Vdbe *)pStmt);

pStmt = 0;

if( rc!=SQLITE_SCHEMA ){

nRetry = 0;

zSql = zLeftover;

while( sqlite3Isspace(zSql[0]) ) zSql++;

}

break;

}

}

sqlite3DbFree(db, azCols);

azCols = 0;

}

exec_out:

if( pStmt ) sqlite3VdbeFinalize((Vdbe *)pStmt);

sqlite3DbFree(db, azCols);

rc = sqlite3ApiExit(db, rc);

/* 对出错信息进行处理 */

if( rc!=SQLITE_OK && ALWAYS(rc==sqlite3_errcode(db)) && pzErrMsg ){ int nErrMsg = 1 + sqlite3Strlen30(sqlite3_errmsg(db));

*pzErrMsg = sqlite3Malloc(nErrMsg);

if( *pzErrMsg ){

memcpy(*pzErrMsg, sqlite3_errmsg(db), nErrMsg);

}else{

rc = SQLITE_NOMEM;

sqlite3Error(db, SQLITE_NOMEM, 0);

}

}else if( pzErrMsg ){

*pzErrMsg = 0;

}

return rc;

}

1.2.2.SQL语句编译的调用层次

当调用sqlite3_prepare()函数时,编译一条SQL语句。编译过程的调用层次如下:

1- sqlite3_prepare()

在prepare.c中。

SQLite现在提供两个版本的编译API函数:遗留的和现在使用的。

在遗留版本中,原始SQL文本没有保存在编译后的语句(sqlite3_stmt结构)中,因此,如果schema发生改变,sqlite3_step()会返回SQLITE_SCHEMA。在新版本中,编译后的语句中保存原始SQL文本,当遇到schema改变时自动重新编译。

sqlite3_prepare()函数中其实只包含一条对sqlite3LockAndPrepare()的调用语句:

rc = sqlite3LockAndPrepare(db,zSql,nBytes,0,ppStmt,pzTail);

其中第4个参数为0,表示不将SQL文本复制到ppStmt中。

空注:源程序中紧跟此函数的sqlite3_prepare_v2()函数中在调用sqlite3LockAndPrepare()时第4个参数为1,不知与上述解释是否矛盾。

2- sqlite3LockAndPrepare()

在prepare.c中。结合注释,很简单,也很清晰。

static int sqlite3LockAndPrepare(

sqlite3 *db, /* 数据库句柄 */

const char *zSql, /* UTF-8编码的SQL语句 */

int nBytes, /* zSql的字节数 */

int saveSqlFlag, /* 如果为True,将SQL文本复制到sqlite3_stmt中。 */ sqlite3_stmt **ppStmt, /* OUT: 指向语句句柄 */

const char **pzTail /* OUT: 未处理的SQL串 */

){

int rc;

*ppStmt = 0;

if( !sqlite3SafetyCheckOk(db) ){ /* 确定db指针的合法性。 */

return SQLITE_MISUSE;

}

/* 将UTF-8编码的SQL语句zSql编译成。 */

rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, ppStmt, pzTail);

if( rc==SQLITE_SCHEMA ){ /* 如果遇到SCHEMA改变,定案,再编译 */

sqlite3_finalize(*ppStmt);

rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, ppStmt, pzTail);

}

return rc;

}

3- sqlite3Prepare()

在prepare.c中。

很长的函数,在其中调用sqlite3RunParser()函数,在给定的SQL字符串上执行分析器。

函数中,先创建Parse结构、加锁什么的,到调用sqlite3RunParser()函数时参数反而很简单了:

sqlite3RunParser(pParse, zSql, &zErrMsg);

此处zSql是一个完整的SQL语句串。

调用返回后还要做一系列处理,略。

4- sqlite3RunParser()

在tokenize.c中。

功能:在给定的SQL字符串上执行分析器。传入一个parser结构。返回一个SQLITE_状态码。如果有错误发生,将错误信息写入*pzErrMsg。

本函数内部是一个循环语句,每次循环处理一个词,根据词的类型做出不同的处理。如果是正经的词(不是空格什么的),都会调用sqlite3Parser()函数对其进行分析。

5- sqlite3Parser()

在parse.c中。

本函数为分析器主程序。

parse.c中的程序好象都是自动生成的,我反正是看不懂,也就不想看了。摘一段与兄弟们共享:

if( yypParser->yyidx < 0 || yymajor==0 ){

yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);

yy_parse_failed(yypParser);

yymajor = YYNOCODE;

}else if( yymx!=YYERRORSYMBOL ){

YYMINORTYPE u2;

u2.YYERRSYMDT = 0;

yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);

}

1.2.3.查询的执行过程

前一小节介绍的编译调用层次看起来还是很清晰的,但实际执行时情况要复杂得多。

比如Oracle一类的数据库,以服务器的形式供客户端访问。在服务器启动的过程中可以完成所有必要的初始化工作,在解析SQL语句时逻辑可能反而简单一些。(Oracle好像也有一些东西在第一次调用时才加载,比如Java虚拟机什么的)。

SQLite这样的数据库主要是提供API供应用程序调用,这就要求在一次单独的调用中要完成所有相关工作。另外,SQLite好像更倾向于将工作留到不得不做时再做(即使不一定非得这样),所以在SQLite中经常会看到“如果还没创建,则创建”或“如果还没打开,则打开”一类的代码。这样,程序的旁枝就会比较多,有时读起来会有一定困难。比如,在SQLite 启动后第1次执行select语句时,在编译该语句的过程中需要完成schema信息内存初始化的全部工作。

下面我们就跟踪一条最简单的select语句的执行过程,从中可以了解SQLite的运行机制。首先要准备数据库。

创建一个新的数据库,创建一个表:

create table d (

id integer primary key,

name text,

loca text );

向表中插入4条记录:

insert into d (name,loca) values ('accounting','Beijing');

insert into d (name,loca) values ('research','Nanjing');

insert into d (name,loca) values ('marketing','Xining');

insert into d (name,loca) values ('operation','Baoding');

执行下列命令:

.m col

.h on

.w 4 15 3 3 3 20 3

explain select * from d;

返回结果如下:

addr opcode p1 p2 p3 p4 p5 comment

---- --------------- --- --- --- -------------------- --- -------

0 Trace 0 0 0 00

1 Goto 0 11 0 00

2 OpenRead 0 2 0

3 00

3 Rewind 0 9 0 00

4 Rowid 0 1 0 00

5 Column 0 1 2 00

6 Column 0 2 3 00

7 ResultRow 1 3 0 00

8 Next 0 4 0 01

9 Close 0 0 0 00

10 Halt 0 0 0 00

11 Transaction 0 0 0 00

12 VerifyCookie 0 2 0 00

13 TableLock 0 2 0 d 00

14 Goto 0 2 0 00

上面显示了一条select语句经编译后所生成的VDBE程序。有关VDBE程序的介绍请参考《SQLite权威指南》[1]。其中相关介绍好像有些过时,主要是由于这部分程序变化比较快,但还是很有参考价值的,反正我看了那部分内容之后,上面的程序就能看懂个大概意思了。

下面,我们就在此数据库基础上跟踪查询语句select * from d的处理过程。主要是罗列在处理过程所执行过的函数。每次调用的相关说明并不多,有的只说明关键变量的值,有的简单说明执行过程。主要是调用的太多了,实在没法对每次调用都详细说明。读者最好按上面的方法创建示例数据库,然后边看边跟踪执行。

注意:函数前面的数字表示调用的层次,而不是序号。

1-sqlite3_exec:

zSql="select * from d;"

2-sqlite3Prepare:

zSql="select * from d;"

调用sqlite3RunParser。

3-sqlite3RunParser:

每处理一个单词,调用一次sqlite3Parser。

当语句处理完毕,语句串变为"",最后一次调用sqlite3Parser。

在sqlite3Parser中,后部有一个do while循环。循环了好多遍,下面一句也执行了好多遍:yy_reduce(yypParser,yyact-YYNSTATE);

yy_reduce中有一个大的switch语句,每次调用执行的分支不同。终于有一遍中调用了sqlite3Select。

sqlite3Select是select语句的处理主程序,在其中又经过如下调用层次(太多,这些层次就没编号了):

sqlite3Select(在select.c中)

sqlite3SelectPrep(在select.c中)

sqlite3SelectExpand(在select.c中)

sqlite3WalkSelect(在walker.c中)

selectExpander(在select.c中)

sqlite3LocateTable(在build.c中)

sqlite3ReadSchema(在prepare.c中)

sqlite3Init(在prepare.c中)。

4-sqlite3Init:

功能:

初始化所有数据库文件——主数据库、临时数据库和所有附加的数据库。返回成功码。如果有错误发生,将错误信息写入*pzErrMsg。

执行:

进入第一个循环语句。在循环语句中调用sqlite3InitOne。

需要注意的是程序中有一小句很重要:

db->init.busy = 1;

当db->init.busy被设为1时,就不会再有VDBE代码生成或执行。后面就可以在回叫函数中通过执行系统表中的create语句的方式为对象创建内部数据结构而又不会实际地执行这些创建语句。

5-sqlite3InitOne:

(在prepare.c中)

功能:

读入一个单独数据库文件的schema,并初始化内部的数据结构。

执行:

调用回叫函数sqlite3InitCallback,执行系统表的创建语句,为系统表创建内部数据结构。

6-sqlite3InitCallback:

(在prepare.c中)

功能:

本函数是初始化数据库时的回叫程序。

执行:

调用sqlite3_exec。

7-sqlite3_exec:

zSql=CREATE TABLE sqlite_master(

type text,

name text,

tbl_name text,

rootpage integer,

sql text

)

8-sqlite3Prepare:

zSql=CREATE TABLE sqlite_master(

type text,

name text,

tbl_name text,

rootpage integer,

sql text

)

7-sqlite3_exec:

从sqlite3Prepare返回后,执行到sqlite3_step一句。

8-sqlite3_step:

sqlite3_step是顶层函数,它调用sqlite3Step完成主要工作。

9-sqlite3Step:

此函数中调用了sqlite3VdbeExec。

10-sqlite3VdbeExec:

p->zSql=""

p->nOp=2

p->aOp:

0 21 OP_Trace

1 40 OP_Halt

可见,不执行实际的创建功能,直接返回。

9-sqlite3Step:

回到sqlite3Step后,发现sqlite3VdbeExec调用的返回结果为101。

rc又与另一个数“与”操作后,值为21,返回。

8-sqlite3_step:

rc值在其后的运算中变为101,返回。

7-sqlite3_exec:

rc!=SQLITE_ROW,不回显,退出循环。返回。

6-sqlite3InitCallback:

返回。

5-sqlite3InitOne:

继续执行,很多语句之后,遇到调用sqlite3_exec,查询系统表的内容。

6-sqlite3_exec:

zSql=SELECT name, rootpage, sql FROM 'main'.sqlite_master

7-sqlite3Prepare:

zSql=SELECT name, rootpage, sql FROM 'main'.sqlite_master

正常返回。

6-sqlite3_exec:

从sqlite3Prepare返回后,在sqlite3_step中经过几层(略)调用到sqlite3VdbeExec。

7-sqlite3VdbeExec:

p->zSql=""

p->nOp=14

p->aOp[]的内容为:

0 21 OP_Trace

1 96 OP_Goto

2 1

3 OP_OpenRead

3 120 OP_Rewind

4 3 OP_Column

5 3 OP_Column

6 3 OP_Column

7 90 OP_ResultRow

8 104 OP_Next

9 34 OP_Close

10 40 OP_Halt

11 101 OP_Transaction

12 97 OP_TableLock

13 96 OP_Goto

可见,这次要真正地执行查询功能。

6-sqlite3_exec:

注:仍然在SELECT name, rootpage, sql FROM 'main'.sqlite_master的STEP循环中。

从sqlite3_step返回后,rc==SQLITE_ROW,继续处理返回的记录。

在“if( xCallback(pArg, nCol, azVals, azCols) ){”一句中调用sqlite3InitCallback,然后,又调用sqlite3_exec。

这里调用sqlite3_exec是要执行系统表中每个对象的创建语句,目的是为这些对象创建内存数据结构。

7-sqlite3_exec:

zSql=

create table d (

id integer primary key,

name text,

loca text )

8-sqlite3Prepare:

zSql=

create table d (

id integer primary key,

name text,

loca text )

7-sqlite3_exec:

从sqlite3Prepare返回后,在sqlite3_step中经过几层(略)调用sqlite3VdbeExec。

8-sqlite3VdbeExec:

p->zSql=""

p->nOp=2

7-sqlite3_exec:

rc!=SQLITE_ROW,不回显,退出循环。返回。

6-sqlite3_exec:

注:仍然在SELECT name, rootpage, sql FROM 'main'.sqlite_master的STEP循环中。

循环处理下一条记录。

从sqlite3Prepare返回后,在sqlite3_step中经过几层(略)调用sqlite3VdbeExec。

7-sqlite3VdbeExec:

p->zSql=""

p->nOp=14

p->aOp[]

6-sqlite3_exec:

继续,sqlite3_step的返回值为101

rc!=SQLITE_ROW,不回显,退出循环。返回。

注:此时sqlite_master表中只有一条记录,至此,已经处理完了。

5-sqlite3InitOne:

返回。

4-sqlite3Init:

退出第一个循环。

又调用sqlite3InitOne。

5-sqlite3InitOne:

调用sqlite3InitCallback,创建临时数据库的系统表。

6-sqlite3InitCallback:

调用sqlite3_exec。

7-sqlite3_exec:

zSql=CREATE TEMP TABLE sqlite_temp_master ...

8-sqlite3Prepare:

zSql=CREATE TEMP TABLE sqlite_temp_master ...

7-sqlite3_exec:

从sqlite3Prepare返回后,在sqlite3_step中经过几层(略)调用sqlite3VdbeExec。

8-sqlite3VdbeExec:

p->zSql=""

p->nOp=2

7-sqlite3_exec:

rc!=SQLITE_ROW,不回显,退出循环。返回。

6-sqlite3InitCallback:

返回。

5-sqlite3InitOne:

继续执行,调用sqlite3_exec。

4-sqlite3Init:

从sqlite3InitOne返回。

3-sqlite3RunParser:

从sqlite3Init经多级返回。

2-sqlite3Prepare:

zSql="select * from d;"

从sqlite3RunParser返回。

1-sqlite3_exec:

zSql="select * from d;"

从sqlite3Prepare返回。至此,在第一次sqlite3Prepare调用中所做的一系列准备工作终于做完了,又回到了对"select * from d;"语句的处理过程中。

顺便说明一下,本次"select * from d;"语句的处理过程完成后,如果马上再次执行"select * from d;"语句,上述准备工作就不需要再做一次了。流程会简单很多。

从sqlite3Prepare返回后,在sqlite3_step中调用sqlite3VdbeExec。

2-sqlite3VdbeExec:

p->zSql="select * from d"

p->nOp=15

p->aOp[]的内容为:

0 21 OP_Trace

1 96 OP_Goto

2 1

3 OP_OpenRead

3 120 OP_Rewind

4 3 OP_Column

5 3 OP_Column

6 3 OP_Column

7 90 OP_ResultRow

8 104 OP_Next

9 34 OP_Close

10 40 OP_Halt

11 101 OP_Transaction

12 99 OP_VerifyCookie

13 97 OP_TableLock

14 96 OP_Goto

可见,这次要真正地执行查询功能。

1-sqlite3_exec:

从sqlite3VdbeExec返回,rc==100==SQLITE_ROW。

在“if( xCallback(pArg, nCol, azVals, azCols) ){”一句中显示一条记录。

2-sqlite3VdbeExec:

p->zSql="select * from d"

p->nOp=15

1-sqlite3_exec:

从sqlite3VdbeExec返回,rc==100==SQLITE_ROW。

显示第2条记录。

2-sqlite3VdbeExec:

p->zSql="select * from d"

p->nOp=15

1-sqlite3_exec:

从sqlite3VdbeExec返回,rc==100==SQLITE_ROW。

显示第3条记录。

2-sqlite3VdbeExec:

p->zSql="select * from d"

p->nOp=15

1-sqlite3_exec:

从sqlite3VdbeExec返回,rc==100==SQLITE_ROW。

显示第4条记录。

2-sqlite3VdbeExec:

p->zSql="select * from d"

p->nOp=15

1-sqlite3_exec:

从sqlite3VdbeExec返回,rc!=SQLITE_ROW。定案并退出循环。

处理过程结束,累死了。

2.SQLite3的内存数据结构

2.1. SQLite体系结构介绍

我一向认为,水平越高的程序员编的程序越简单,越容易看懂,就好比水平越高的领导越能将问题简单化,而不是先把单位搞得鸡犬不宁然后自己也累得吐血。(这篇东西写得这么晦涩,作者水平也就可见一斑了)

SQLite的原作者们水平都很高,程序技巧性很强,但我看源程序时还是经常遇到困难,除了我真笨外,还有以下原因:

1-SQLite是实用程序,不是教学程序。一般实用程序在其功能主线之外都会附加一些代码,以保证程序的健壮性或完成测试功能等,SQLite在这方面尤其过分。

2-缺少SQLite实现的背景知识,缺少数据库实现的背景知识,总之,我没文化。

3-缺少对SQLite体系结构的深入了解。有这方面的介绍,都很笼统,本章就是对这类介绍的一个补充。

其实,我费了这么大劲读程序,也就是搞清了本章的内容,搞清本章的内容之后再读程序,就变得比较简单了。“数据结构”很重要。

先来看下面代码,相信兄弟们都看得懂。该代码例示了在SQLite上执行一个查询的一般过程。

#include

#include

#include"sqlite3.h"

#include

#pragma comment(lib, "sqlite3.lib")

int main(int argc,char **argv)

{

int rc,i,ncols;

sqlite3 *db;

sqlite3_stmt *stmt;

char *sql;

const char*tail;

//打开数据

rc=sqlite3_open("foods.db",&db);

if(rc){

fprintf(stderr,"Can'topendatabase:%sn",sqlite3_errmsg(db));

sqlite3_close(db);

exit(1);

}

sql="select * from episodes";

//预处理

rc=sqlite3_prepare(db,sql,(int)strlen(sql),&stmt,&tail);

if(rc!=SQLITE_OK){

fprintf(stderr,"SQLerror:%sn",sqlite3_errmsg(db));

}

rc=sqlite3_step(stmt);

ncols=sqlite3_column_count(stmt);

while(rc==SQLITE_ROW){

for(i=0;i

fprintf(stderr,"'%s'",sqlite3_column_text(stmt,i));

}

fprintf(stderr,"\n");

rc=sqlite3_step(stmt);

}

//释放statement

sqlite3_finalize(stmt);

//关闭数据库

sqlite3_close(db);

printf("\n");

return(0);

}

程序就不解释了。在上述程序中,使用了两个结构的指针,分别是sqlite3和sqlite3_stmt。SQLite中有数不清的结构,而这两个结构正是SQLite数据处理的两大主线。学《数据结构》时讲究先研究存储结构再研究算法,对SQLite来说,搞清这两个结构之后,再读程序就会变得很容易了。

下图是SQLite官方网站对SQLite体系结构的描述,详细说明见参考文献1。

图2-1 SQLite体系结构

在SQLite的实现中,无论是代码的设计还是数据结构的设计都是按上述体系结构完成的,层次非常清晰。SQLite中有数不清的结构,我们只按照两大主线介绍其中的不到20种,如下图所示。图中的箭头代表包含关系,可以看出,这些结构也是按照上述体系结构组织的。

sqlite3常用命令及语法

https://www.doczj.com/doc/8b12809955.html,/linchunhua/article/details/7184439 sqlite数据库只用一个文件就ok,小巧方便,所以是一个非常不错的嵌入式数据库,SQLite 大量的被用于手机,PDA,MP3播放器以及机顶盒设备。 Mozilla Firefox使用SQLite作为数据库。 Mac计算机中的包含了多份SQLite的拷贝,用于不同的应用。 PHP将SQLite作为内置的数据库。 Skype客户端软件在内部使用SQLite。 SymbianOS(智能手机操作平台的领航)内置SQLite。 AOL邮件客户端绑定了SQLite。 Solaris 10在启动过程中需要使用SQLite。 McAfee杀毒软件使用SQLite。 iPhones使用SQLite。 Symbian和Apple以外的很多手机生产厂商使用SQLite。 下面就sqlite中的常用命令和语法介绍 https://www.doczj.com/doc/8b12809955.html,/download.html可下载不同操作系统的相关版本sqlite gedit 也可以使用火狐中的插件sqlite manager 新建数据库 sqlite3 databasefilename 检查databasefilename是否存在,如果不存在就创建并进入数据库(如果直接退出,数据库文件不会创建)如果已经存在直接进入数据库对数据库进行操作 sqlite中命令: 以.开头,大小写敏感(数据库对象名称是大小写不敏感的) .exit .help 查看帮助针对命令 .database 显示数据库信息;包含当前数据库的位置 .tables 或者.table 显示表名称没有表则不显示 .schema 命令可以查看创建数据对象时的SQL命令; .schema databaseobjectname查看创建该数据库对象时的SQL的命令;如果没有这个数据库对象就不显示内容,不会有错误提示 .read FILENAME 执行指定文件中的SQL语句 .headers on/off 显示表头默认off .mode list|column|insert|line|tabs|tcl|csv 改变输出格式,具体如下 sqlite> .mode list sqlite> select * from emp; 7369|SMITH|CLERK|7902|17-12-1980|800||20 7499|ALLEN|SALESMAN|7698|20-02-1981|1600|300|30 如果字段值为NULL 默认不显示也就是显示空字符串

sqlite3使用教程

Sqlite3教程 一、基本命令 1、进入命令行环境: 显示版本号,并告诉每一条SQL语句必须用分号;结尾2、命令行帮助:

3、退出命令行环境 或者 二、数据库相关命令 1、创建(或打开)一个新的数据库:文件名 若文件存在,刚打开该文件;若文件不存在,则创建一个*.db数据库文件。 导入SQL语句文件。

、列出所有数据表: 4、显示数据库结构: 用一些SQL语句描述数据库的结构。 5、显示表的结构:表名 6、导入数据:文件名表名 若导入csv文件,设置分隔符为逗号。 、导出数据:文件名 查询结果默认在终端显示,查询表格结构,语句查询表格数据。设置查询目标后,查询结果显示在设置的文件中 文件名 然后输入sql查询语句,查询的结果显示在设置的文件中,不在终端显示 运行恢复导出到终端(标准输出)。 导出数据到excle表格中 设置分隔符为逗号: 设置导出文件名,后缀为csv: 查询语句:表名

三、数据显示命令 运行表名,显示全表的内容 1.设置分隔符:分隔符 默认分隔符是“|”。 2.设置显示模式:模式

默认的是list显示模式,一般使用column模式。 3.显示标题栏: 4.设置每一列的显示宽度: 5.列出当前显示格式设置情况: 四、数据库基本操作 1.数据库定义语言DDL 在关系型数据库中,数据库中的表table、视图、索引、关系和触发器等等,构成了数据库的架构。在SQL语句中,专门有一些语句用来定义数据库架构,这些语句被称为“数据库定义语言”,即DDL。 SQLite数据库引擎支持下列三种DDL语句: ●CREATE:创建 ●ALTER TABLE:改变表的结构 ●DROP:删除

SQLITE3的操作方法及应用

数据库的操作 我们在这个项目中使用的是SQLITE3数据库软件。 通过使用SQLITE3进行创建数据库,创建表,插入记录,查询记录,更新记录,关闭数据库等操作来实现将相应的数据存入数据库中。 1.打开数据库,创建表 1.1sqlite*db;定义一个sqlite*的变量 sqlite3_open(“./link.db”,&db); 在当前目录下打开一个名为link.db的数据库,若是没有则在当前目录下创建一个名为link.db 的数据库。 1.2sql="create table weblink(id integer primary key,domain text,page text,fromdomain text,status integer);" 在已打开的数据库中创建一个名weblink的表。表的属性如下: id integer primary key:ID号(表中黙认包含的) domain text:域名 page text:子网页 fromdomain text:源域名 status integer:状态标志 1.3sqlite3_exec(db,sql,NULL,NULL,NULL); 执行一条sql语句的函数。 函数原型:int sqlite3_exec(sqlite3*,const char*sql,sqlite3_callback,void*,char**errmsg) 第1个参数是前面open函数得到的指针。说了是关键数据结构。 第2个参数const char*sql是一条sql语句,以\0结尾。 第3个参数sqlite3_callback是回调,当这条语句执行之后,sqlite3会去调用你提供的这个函数。(什么是回调函数,自己找别的资料学习) 第4个参数void*是你所提供的指针,你可以传递任何一个指针参数到这里,这个参数最终会传到回调函数里面,如果不需要传递指针给回调函数,可以填NULL。等下我们再看回调函数的写法,以及这个参数的使用。 第5个参数char**errmsg是错误信息。注意是指针的指针。sqlite3里面有很多固定的错误信息。执行sqlite3_exec之后,执行失败时可以查阅这个指针(直接printf(“%s\n”,errmsg))得到一串字符串信息,这串信息告诉你错在什么地方。sqlite3_exec函数通过修改你传入的指针的指针,把你提供的指针指向错误提示信息,这样sqlite3_exec函数外面就可以通过这个char*得到具体错误提示。 说明:通常,sqlite3_callback和它后面的void*这两个位置都可以填NULL。填NULL表

sqlite 基本操作 全

sqlite3本地数据库学习 sqlite3只是一个轻型的嵌入式数据库引擎,占用资源非常低,处理速度比mysql还快,专门用于移动设备上进行适量的数据存取,它只是个文件,不需要服务器进程。 常用术语:表(table)、字段(colum,列,属性)、记录(row,record) 关键字:select、insert、updete、delete、from、creat、where、desc、order、by、group、table、alter、view、index等。 1、安装sqlite3 sudo()apt-get()install()sqlite3 2、存储类型 integer 整型:int,shoert,long text 文本字符串:string real 浮点型:float,double blob 二进制 3、字段结束 not null:字段的值不能为空 unique:字段的值必须是唯一的 default:指定字段的默认值 primarykey:主键,用来唯一的标识某条记录,相当于记录的身份证。主键可以是一个或多个字段,应由计算机自动生成和管理。主键字段默认包含了not null和unique两个约束。 autoincrement:当主键是integer类型时,应该增加autoincrement约束,能实现主键值的自动增长。 外键:利用外键可以用来建立表与表之间的联系,一般是一张表的某个字段,引用着另一张表的主键。 4、创建数据库usr.db在当前目录下 sqlite3()usr.db 5、创建表格,表格内容以树状存储 create()table()表名(字段名1()字段类型1,字段名2()字段类型2...) 6、数据库中不能使用关键字命名表和字段,不区分大小写,每条语句后加";"结尾 7、删除表格 drop()table()表名 8、向表格里添加数据 insert()into()表名(字段1,字段2...)values(字段1的值,字段2的值...) 8、修改表中的数据 updata()表名()set()字段1=字段1的值,字段2=字段2的值... //将字段为name全部修改成'Tom' updata()stu()set()name='Tom'; //将字段为id=1001的字段name修改成'Tom' updata()stu()set()name='Tom'()where()id=1001; //将字段为id=1001同时字段name='lisi'的字段name修改成'Tom' updata()stu()set()name='Tom'()where()id=1001()and()name='lisi'; 9、删除表中的数据

QSQLite 数据库

这里我们只是演示了一下使用这个框架完成最简单的程序的过程,只起到抛砖引玉的作用。这个框架很复杂,但是功能也很强大,Qt Creator中自带了几个相关的例子(在帮助中查找Graphics View Examples即可),你可以参考一下。因为篇幅问题,我们就只讲这么多,如果以后有机会,我会推出一个相关的专题来讲述这个框架。 分类:Qt系列教程作者: yafeilinux 日期:四月 30th, 2010. 3,006 views Tags: 2D绘图, creator, qt, yafeilinux, 教程

二十一、Qt数据库(一)简介 本文章原创于https://www.doczj.com/doc/8b12809955.html,转载请注明出处。 从今天开始我们学习Qt数据库编程的内容。 先说明:我们以后使用现在最新的基于Qt 4.6.2的Qt Creator 1.3.1 Windows版本,该版本是2010年2月17日发布的。 数据库几乎是每个较大的软件所必须应用的,而在Qt中也使用QtSql模块实现了对数据库的完美支持。我们在Qt Creator的帮助中查找QtSql Module,其内容如下图: 可以看到这个模块是一组类的集合,使用这个模块我们需要加入头文件#include ,而在工程文件中需要加入一行代码:QT += sql 这里每个类的作用在后面都有简单的介绍,你也可以进入其中查看其详细内容。下面我们先简单的说一下QSqlDatabase类和QSqlQuery类。 QSqlDatabase类实现了数据库连接的操作,现在Qt支持的数据库类型有如下几种: 而现在我们使用的免费的Qt只提供了SQLite和ODBC数据库的驱动(我们可以在Qt Creator 安装目录下的qt\plugins\sqldrivers文件夹下查看),而其他数据库的驱动需要我们自己添加。SQLite是一个小巧的嵌入式数据库,关于它的介绍你可以自己在网上查找。 QSqlQuery类用来执行SQL语句。(关于SQL语句:在我的教程中只会出现很简单的SQL语句,你没有相关知识也可以看懂,但是如果想进行深入学习,就需要自己学习相关知识了。)

SQLITE最基本操作

SQLite数据库的基本操作 main.xml(主布局)

android:orientation="vertical">

sqlite3在Linux下的安装和使用

sqlite3在Linux下的安装和使用 2008-06-10 16:51:14| 分类:sqlite|字号订阅 一.sqlite3的安装和配置 下载sqlite3源码包 tar xvfz sqlite-src-3.3.5 cd sqlite-3.3.5 ./configure –no-tcl make (如果在arm板上用需修改Makefile,在LIBS 项中加入–L/usr/local/arm/3.3.2/lib 保存后退出.然后再make) 安装成功后生成文件将被复制到指定目录 再加入一个环境变量 vi /etc/profile 在export区域加入SQLITE3_PATH=/usr/local/sqlite-3.3.5 保存后退出 source /etc/profile 有用文件分别为$SQLITE3_PATH/include/sqlite3.h 头文件 $SQLITE3_PATH/bin/sqlite3 可执行文件 $SQLITE3_PATH/lib/libsqlite3.a https://www.doczj.com/doc/8b12809955.html, libsqlite3.so -> libsqlite3.so.0.8.6 libsqlite3.so.0 -> libsqlite3.so.0.8.6 libsqlite3.so.0.8.6 在程序使用到数据库 #include

在.pro文件中添加: INCLUDEPATH +=$(SQLITE3_PATH)/include DEPENDPATH +=$(SQLITE3_PATH)/include LIBS +=-L$(SQLITE3_PATH)/lib LIBS +=-lsqlite3 保存后退出 tmake hello.pro –o Makefile make 二.程序的编写: sqlite3 *db; int rc = sqlite3_open(“data.db”,&db); //打开数据库data.db if(rc!=SQLITE_OK);//打开失败 创建表rc = sqlite3_exec(db,”create table student(ID integer primarykey,name nvarchar(32))”,NULL,NULL,&mrrmsg); 插入rc = sqlite3_exec(db,”insert into student values(…3?,?Zhang San?)”,0,0,&mrrmsg); 修改rc = sqlite3_exec(db,”update student set name=?Li Si? where ID=?4?”,0,0,&mrrmsg);删除rc = sqlite3_exec(db,”delete * from student where name=?Wang Wu?”,0,0,&mrrmsg); 查询是重点 回调式查询rc = sqlite3_exec(db,”select * from student where ID>2 and name<>?Zhang San?”,LoadInfo,NULL,&mrrmsg); 查询的结果通过LoadInfo函数来导出

Unity3D教程:Unity3D与Sqlite数据库直连

Unity3D教程:Unity3D与Sqlite数据库直连 Posted on 2013年01月10日 by U3d / Unity3D 基础教程/被围观 475 次环境介绍: Windows7,Unity3D,SQLite Expert Personal 3 开发语言: JavaScript 需要的dll文件: Mono.Data.Sqlite.dll和sqlite3.dll,dll文件位置,截图: Unity3D教程:Unity3D与Sqlite数据库直连一定要在这个目录下,请保持一致。 如果需要将编译好的程序发布成功的话,需要改一些地方,具体见下面的截图:

Unity3D教程:Unity3D与Sqlite数据库直连 要改动的地方已用红色标记,注意这个要改成.NET2.0,这样才能够发布的。系统默认的不是.NET2.0,这一点要注意!!! 下面来看下代码吧,先看下如何创建数据库的代码,这一篇代码是不用挂到任何对象上面去的,你只用把它当成一个工具即可。如下所示: /* Javascript class for accessing SQLite objects. To use it, you need to make sure you COPY Mono.Data.SQLiteClient.dll from wherever it lives in your Unity directory

to your project's Assets folder Originally created by dklompmaker in 2009 https://www.doczj.com/doc/8b12809955.html,/threads ... sier-Database-Stuff Modified 2011 by Alan Chatham */ //#pragma strict /* 代码描述 *本代码是为了在Windows环境下运行unity3d和Sqlite数据库而写的;实现的基本功能是unity3d能够与数据库之间进行基本的通信,比如说:在数据库中的数据被改变了以后,unity3d中得到的数据也会在刷新了之后跟着改变;这只是一个基本的核心的技术,为的是能够应用在大型的unity3d项目中,能够存储场景中的项目的属性,在需要改变对象的属性或增加、减少等对象时能够很方便的用得上。要实现本代码。首先需要一些dll文件,一个是Mono.Data.SQLiteClient.dll,另外一个是sqlite3.dll,这些文件都能够在unity3d的安装目录中找得到。除此之外,还需要把这两个文件放在你的项目的这个路径下面:\Assets\Plugins\,没有Plugins文件夹就必须创建这个文件夹,然后将这两个dll文件放在该文件夹写。当然,如果你想能够在PC上面发布成可执行文件,还需要改动

SQLite3 API使用大全

SQLite3API使用大全E-mail:18918737 (at) qq dot com,智有不明

前序: (1) 一、版本 (1) 二、基本编译 (2) 三、 SQLITE操作入门 (2) (1)基本流程 (2) (2) SQL语句操作 (4) (3)操作二进制 (8) (4)事务处理 (10) 四、给数据库加密 (10) 五、后记 (25) 前序: Sqlite3 的确很好用。小巧、速度快。但是因为非微软的产品,帮助文档总觉得不够。这些天再次研究它,又有一些收获,这里把我对 sqlite3 的研究列出来,以备忘记。 这里要注明,我是一个跨平台专注者,并不喜欢只用 windows 平台。我以前的工作就是为unix 平台写代码。下面我所写的东西,虽然没有验证,但是我已尽量不使用任何 windows 的东西,只使用标准 C 或标准C++。但是,我没有尝试过在别的系统、别的编译器下编译,因此下面的叙述如果不正确,则留待以后修改。 下面我的代码仍然用 VC 编写,因为我觉得VC是一个很不错的IDE,可以加快代码编写速度(例如配合 Vassist )。下面我所说的编译环境,是VC2003。如果读者觉得自己习惯于 unix 下用 vi 编写代码速度较快,可以不用管我的说明,只需要符合自己习惯即可,因为我用的是标准 C 或 C++ 。不会给任何人带来不便。 一、版本 从https://www.doczj.com/doc/8b12809955.html,网站可下载到最新的 sqlite 代码和编译版本。我写此文章时,最新代码是 3.3.17 版本。 很久没有去下载 sqlite 新代码,因此也不知道 sqlite 变化这么大。以前很多文件,现在全部合并成一个 sqlite3.c 文件。如果单独用此文件,是挺好的,省去拷贝一堆文件还担心有没有遗漏。但是也带来一个问题:此文件太大,快接近7万行代码,VC开它整个机器都慢下来了。如果不需要改它代码,也就不需要打开 sqlite3.c 文件,机器不会慢。但是,下面我要写通过修改 sqlite 代码完成加密功能,那时候就比较痛苦了。如果个人水平较高,建议用些简单的编辑器来编辑,例如 UltraEdit 或 Notepad 。速度会快很多。 二、基本编译 这个不想多说了,在 VC 里新建 dos 控制台空白工程,把 sqlite3.c 和 sqlite3.h 添加到工程,再新建一个 main.cpp 文件。在里面写: extern "C" { #include "./sqlite3.h" }; int main( int , char** ) { return 0; }

Sqlite使用文档

SQLite的配置和使用文档 一.引言: 本文将简要介绍如何在Linux和ARM-Linux平台上移植SQLite嵌入式数据库,以及一些简单的测试案例。 嵌入式数据库采用程序方式直接驱动,而传统数据库则采用引擎响应方式驱动。由于嵌入式数据库的体积通常很小,这使得嵌入式数据库常常应用在移动设备上。 SQLite是一种嵌入式数据库。SQLite的目标是尽量简单,因此它抛弃了传统企业级数据库的种种复杂特性,只实现那些对于数据库而言非常必要的功能。尽管简单性是SQLite追求的首要目标,但是其功能和性能都非常出色由于SQLite具有功能强大、接口简单、速度快、占用空间小等优点,因此特别适合于应用在嵌入式环境中。SQLite在手机、PDA、机顶盒等设备上已获得了广泛应用。 二.软硬件平台: OS:fedora7; 编译器:gcc 版本 4.1.2 20070502 (Red Hat 4.1.2-12): 开发板:基于Sep4020的UB4020EVB(1.6) 开发套件; Linux内核:Linux Kernel v2.6.16: 交叉编译器:gcc version 3.4.1: Sqlite:sqlite-3.3.8 三.PC端编译环境的安装: 此处使用的为SQLite版本为sqlite-3.3.8.tar.gz,可以通过以下方式获得此压缩包https://www.doczj.com/doc/8b12809955.html,/sqlite-3.3.8.tar.gz(利用迅雷等工具下载)。 将此压缩包拷贝到/root目录下,在终端中进入此目录,并解压sqlite-3.3.8.tar.gz压缩包:

[root@localhost ~]# cd /root/ [root@localhost ~]# tar -zxvf sqlite-3.3.8.tar.gz 将sqlite-3.3.8更名为sqlit_pc,并进入sqlite_pc目录: [root@localhost ~]# mv sqlite-3.3.8 sqlite_pc [root@localhost ~]# cd sqlite_pc //进入目录后采用默认配置生成Makefile文件: [root@localhost sqlite_pc]# ./configure 配置结束后进行编译并且将所生成的文件安装: [root@localhost sqlite_pc]# make [root@localhost sqlite_pc]# make install Make install 安装以后会生成以下文件,系统默认的目录为/usr/local: lib:libsqlite3.a https://www.doczj.com/doc/8b12809955.html, libsqlite3.so libsqlite3.so.0 libsqlite3.so.0.8.6 include:sqlite3.h bin: sqlite3 由于/usr/local为系统路径,此时只要在终端直接输入sqlite3 [数据库名] 即可打开(没有时创建)一个数据库文件。 例1:在终端输入以下语句: [root@localhost sqlite-3.3.8]# sqlite3 prochip.db SQLite version 3.3.8 Enter ".help" for instructions sqlite> 此时就会正确的打开(没有时创建)prochip.db数据库文件。

SQLite Expert Personal使用教程

小蛙今天要介紹一套圖形化的SQLite管理軟體,目前像Android, iOS … 等手持式裝置內部都支援使用SQLite,不外乎是因為它方便、小、速度快,SQLite不像一般MySQL、Oracle、MSSQL這麼複雜,我們可以把SQLite想像成一個檔案(實際上存好之後也只有一個檔案),但這一個檔案又比Microsoft Access有更大的便利性(可以在很多平台使用,不會只鎖定微軟平台),想更了解SQLite可以參考、或者是。是小蛙今天要介紹的軟體,它不只可以瀏覽SQLite內儲存的資料,同時也可以進行新增、修改、刪除…等操作,就像官網首頁寫的「SQLite Expert: A powerful administration tool for your SQLite databases」。 注意:這篇文章主要是以圖形化工具操作SQLite,並不會讓你學到SQLite指令操作。 先到官網下載SQLite Expert Personal免費版,上面的是專業版,只能試用30天,那小蛙只是需要一些資料庫基本操作,選擇下面的License是Freeware的個人免費版。下載完之後安裝,預設一直下一步直到安裝完成。 安裝完成後執行SQLite Expert Personal,在桌面可以看到圖示,如果沒有的話到開始所有程式(程式集)裡面去找「SQLite Expert」,點兩下執行。

啟動之後我們必須先建立一個新的資料庫,點選左上角紅色框框新增資料庫,並且輸入相關設定。 新增完資料庫後,畫面左邊可以看到小蛙剛剛新增的資料庫「postman」,在資料庫上點選滑鼠右鍵,選擇「New Table」來新增需要的表單。

C C++中使用SQLite_3 数据库

在C/C++中使用SQLite 廖卫东

C/C++接口 SQLite3.0依据以下需求而创建: 支持UTF-16。 用户可定义的文本排序。 以索引列的形式存储BLOB。 SQLite3.0的API包括了83个独立的函数。简单的程序可以通过三个函数工作:sqlite3_open()、sqlite3_exec()和 sqlite3_close()。 更多的数据库引擎运行控制可以用sqlite3_prepare()来编译一个SQLite语句成字节代码并通过sqlite3_step()来执行它。 一个用sqlite3_column_开头的命令序列可以用来提取关于查询结果的信息。许多接口函数是以UTF-8和UTF-16的形式成对出现的。并且有一个用于实现用户定义SQL函数和用户定义的text比较。

打开与关闭一个数据库 typedef struct sqlite3 sqlite3; int sqlite3_open(const char*, sqlite3**); int sqlite3_open16(const void*, sqlite3**); int sqlite3_close(sqlite3*); sqlite3_open()程序返回一个整型错误代码,而不是像sqlite2做的那样返回一个指向sqlite3结构。sqlite3_open()与 sqlite3_open16()间的区别是sqlite3_open16()采用UTF-16(以本地字节顺序)作为数据库文件名。如果一个新数据库文件需要被创建,那么sqlite3_open16()设置本地的文本表达式为UTF-16而sqlite3_open()设置文本表达式为UTF-8。

PHP进行SQLite实例教程

PHP进行SQLite实例教程 PHP进行SQLite实例教程文章录入:https://www.doczj.com/doc/8b12809955.html, 责任编辑:https://www.doczj.com/doc/8b12809955.html, 63【字体:小大】本教程将向你介绍SQLite API所支持的重要方法,提供一个能够用在你开发中的简单脚本模板,从而告诉你如何使用PHP与SQLite数据库进行交互操作。本文假设你已经安装好了Apache和PHP。 你的系统上并不是一定非要安装可交互的SQLite 程序;但是为了能够简化创建本教程所需要的一系列初始表格,你应该下载和安装这个程序。然后,为你的SQL查询创建一个示例表格,方法是创建一个空白的文本文件,将该文件名作为下列命令(列表A)的参数在交互命令提示符下执行二进制程序: sqlite> CREATE TABLE users (id INTEGER PRIMARY KEY, username TEXT, country TEXT); sqlite> INSERT INTO users VALUES (1, 'john', 'IN'); sqlite> INSERT INTO users VALUES (2, 'joe', 'UK'); sqlite> INSERT INTO users VALUES (3, 'diana', 'US');一旦表格创建好了,下面就是使用PHP的SQLite方法建立一个脚本模板。 <?php

// set access parameters $db = "users.db"; // open database file // make sure script has read/write permissions! $conn = sqlite_open($db) or die ("ERROR: Cannot open database"); // create and execute INSERT query $sql = "INSERT INTO users (id, username, country) VALUES ('5', 'pierre', 'FR')"; sqlite_query($conn, $sql) or die("Error in query execution: " . sqlite_error_string(sqlite_last_error($conn))); // create and execute SELECT query $sql = "SELECT username, country FROM users"; $result = sqlite_query($conn, $sql) or die("Error in query execution: " . sqlite_error_string(sqlite_last_error($conn))); // check for returned rows // print if available if (sqlite_num_rows($result) > 0) { while($row = sqlite_fetch_array($result)) { echo $row[0] . " (" . $row[1] . ") "; } }

sqlite3的数据类型详解

sqlite3中的数据类型 大多数的数据库引擎(到现在据我们所知的除了sqlite的每个sql数据库引擎)都使用静态的、刚性的类型,使用静态类型,数据的类型就由它的容器决定,这个容器是这个指被存放的特定列。 Sqlite使用一个更一般的动态类型系统,sqlite中,值的数据类型跟值本身相关,而不是与它的容器相关。Sqlite的动态类型系统和其他数据库的更为一般的静态类型系统相兼容,但同时,sqlite中的动态类型允许它能做到一些传统刚性类型数据库所不可能做到的事。 1.存储类和数据类型 每个存放在sqlite数据库中(或者由这个数据库引擎操作)的值都有下面中的一个存储类: ●NULL,值是NULL ●INTEGER,值是有符号整形,根据值的大小以1,2,3,4,6或8字节存放 ●REAL,值是浮点型值,以8字节IEEE浮点数存放 ●TEXT,值是文本字符串,使用数据库编码(UTF-8,UTF-16BE或者UTF-16LE) 存放 ●BLOB,只是一个数据块,完全按照输入存放(即没有准换) 从上可以看出存储类比数据类型更一般化。比如INTEGER存储类,包括6中不同长度的不同整形数据类型,这在磁盘上造成了差异。但是只要INTEGER值被从磁盘读出进入到内存进行处理,它们被转换成最一般的数据类型(8-字节有符号整形)。 Sqlite v3数据库中的任何列,除了整形主键列,可以用于存储任何一个存储列的值。sql语句中的中所有值,不管它们是嵌入在sql文本中或者是作为参数绑定到一个预编译的sql语句,它们的存储类型都是未定的。在下面描述的情况中,数据库引擎会在查询执行过程中在数值(numeric)存储类型(INTEGER和REAL)和TEXT 之间转换值。 1.1布尔类型 Sqlite没有单独的布尔存储类型,它使用INTEGER作为存储类型,0为false,1为true 1.2 Date和Time Datatype Sqlite没有另外为存储日期和时间设定一个存储类集,内置的sqlite日期和时间函数能够将日期和时间以TEXT,REAL或INTEGER形式存放 ●TEXT 作为IS08601字符串("YYYY-MM-DD HH:MM:SS.SSS") ●REAL 从格林威治时间11月24日,4174 B.C中午以来的天数 ●INTEGER 从 1970-01-01 00:00:00 UTC以来的秒数 程序可以任意选择这几个存储类型去存储日期和时间,并且能够使用内置的日期和时间函数在这些格式间自由转换 2.0 类型近似

SQLite数据库常用命令

SQLite数据库入门及常用命令 SQLite软件包中包含了一个名字叫做sqlite3的命令行,它可以让用户手工输入并执行面向SQLite数据库的SQL命令。本文档提供了一个较为详尽的关于sqlite3的使用说明。 启动sqlite3程序,仅仅需要敲入带有SQLite数据库名字的“sqlite3”命令即可。如果文件不存在,则创建一个新的数据库文件。然后,sqlite3程序将提示你输入SQL语句。敲入SQL语句,以分号“;”结束,敲击回车键后,SQL语句就会执行。 例如,创建一个包含一个表“tbl1”名称为“ex1”的SQLite数据库,你可以这样操作: 你可以通过敲击你所用系统的文件结束符(通常是Ctrl+D)或者中断字符(通常是Ctrl+C),来终止sqlite3程序。请记得在每个SQL语句结束后敲入分号!sqlite3程序通过查找分号来决定一个SQL语句是否结束。如果你省略分号,sqlite3将给你一个连续的命令行提示符并等你给当前的SQL命令添加更多的文字。这个特点很利于多行的SQL语句输入。 SQLite数据库的框架被保存在一个名叫“sqlite_master”的特殊表中。你可以像查询其他表一样通过执行“SELECT”语句查询这个特殊的表:

但是,我们不能在sqlite_master表中执行诸如DROP TABLE、UPDATE、INSERT或者DELETE之类的命令。Sqlite_master表在你创建、删除和索引数据库时自动更新这个表。我们不能手工地更改这个表。 temporary表的结构没有存储在“sqlite_master”表中,这是由于temporary表对应用是不可见的,而不是应用程序创建的。temporary表的结构是被存储在另外一个名叫“sqlite_temp_master”的特定表中。 sqlite3的特殊命令。大多数的时候,sqlite3读入用户输入的行,并把它们传递到SQLite库中去运行。但是,如果用户输入的行以一个点“.”开始,那么,这行将被sqlite3程序自身截获并进行解释。这些“点命令”通常被用来改变查询输出的格式,或者执行某个预定义的查询语句。 你可以在任何时候输入“.help”,列出可用的“点命令”。 sqlite3命令可以以8中不同的格式输出查询结果:“csv”、“列”、“html”、“插入”、“行”、“制表”和“tcl”。你可以使用“.mode”这个点命令来在这些输出格式之间进行切换。 默认的输出格式是“列表”。在列表模式下,每条查询结果记录被写在一行中,并且,每列之间以一个字符串分隔符隔开。默认的分隔符是一个管道符号“|”。列表符号模式在当你输出查询结果到另外一个字符处理器的程序(如awk)中时是尤为有用的: 我们也可以使用“.separator”点命令来改变分界符。例如,为了把分隔符改为一个逗号和空格,我们可以这么做:

易语言外部数据库sqlite3教程

易语言外部数据库sqlite3教程 =========================================================== 第一部分 sqlite基础 ----------------------------------------------------------- 1、什么是sqliet SQLite是一个软件库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite是一个增长最快的数据库引擎,这是在普及方面的增长,与它的尺寸大小无关。SQLite 源代码不受版权限制。 SQLite与其他SQL数据库不同,SQLite没有单独的服务器进程。它直接读取和写入普通磁盘文件。具有多个表,索引,触发器和视图的完整SQL数据库包含在单个磁盘文件中。 ----------------------------------------------------------- 2、为什么要用 SQLite? 不需要一个单独的服务器进程或操作的系统(无服务器的)。 SQLite 不需要配置,这意味着不需要安装或管理。 一个完整的 SQLite 数据库是存储在一个单一的跨平台的磁盘文件。 SQLite 是非常小的,是轻量级的,完全配置时小于 400KiB,省略可选功能配置时小于250KiB。 SQLite 是自给自足的,这意味着不需要任何外部的依赖。

SQLite 事务是完全兼容 ACID 的,允许从多个进程或线程安全访问。 SQLite 支持 SQL92(SQL2)标准的大多数查询语言的功能。 SQLite 使用 ANSI-C 编写的,并提供了简单和易于使用的API。 SQLite 可在 UNIX(Linux, Mac OS-X, Android, iOS)和Windows(Win32, WinCE, WinRT)中运行。 ----------------------------------------------------------- 3、常用易语言单机的、免费、轻量级数据库比较 易语言自带数据库易数据库可以说不能称为数据库,它只是“表”,而且还是单张表,所以直接PASS掉。 大部分人会用access,其实Access数据库本身有很多的问题:性能不行;数据不安全,用户可以直接用Access打开数据库文件进行数据修改,即使加密后都可以直接破解;Access的数据量一大,文件本身的体积就异常庞大等因素。 SQLite是一个小型的C程序库,实现了独立的,可嵌入的,零配置的SQL数据库引擎。 SQLite就是Access理想的替代品。 ----------------------------------------------------------- 4、sqlite3数据类型 SQLite存储类比数据类型更通用一些。类型比其他数据库的数据类型少,但是更实用些。

zend studio详细使用教程

zend studio详细使用教程 这一部分是让大伙儿熟悉Zend Studio集成开发环境的界面布局,以及菜单、工具栏命令的功能介绍。目的是熟悉开发环境,明白zde到底都给我们提供了什么?或者这些都是干什么用的?本文将以图文并茂的方式呈现给大家。 先看一下整个界面的截图 窗口界面: ?编辑器:主区域的一个窗口,用来编写代码的,能同时打开多个代码编辑窗口,具强大的提示、语法检查和代码高亮功能,支持php、html代码,是不可多得的神器级编辑工具。 ?浏览器(Browser):zde内置的一个标准的互联网web浏览器,其调试工具栏又让它成为使用zend studio进行调试时的重要组成部分(关于zend studio强大的调试功能,我会在后面单独撰文以讲之。) ?文件管理器:zend studio 5.5.1版的文件管理器窗口包含了3个选项卡:①文件系统:可以浏览本地硬盘上所有的文件,并可以选择性的打开使用编辑器对其编辑;②项目:在该选项卡您可以方便的进行项目的新建、打开、保存以及添加等操作,这些操作都藏在右键快捷菜单中;③SQL:这里是管理数据库连接的,zend studio 5.5.1版支持以下数据库连接:Oracle、SQLite、MSSQL、PostgreSQL、MYSQL、DB2等等。 ?检查器:该窗口包含了3个子选项卡:①文件检查器:列出了编辑器当前打开文件的引用文件、常量、自定义函数等等;②项目检查器:列出了当前项目的所有定义类、函数、常量等内容;③列出当前使用的php版本(zde支持php4和php5,可以在首选项中设置切换)。

?调试窗口:调试窗口包含了5个选项卡:①断点:显示所有设置的断点;②堆栈:调试时显示调用堆栈;③监视点:显示已定义的监视点;④变量:调试时显示全局和局部变量;⑤输出缓冲区:调试时显示脚本的缓冲区数据。 ?消息窗口:用于查看zde在编译时产生的包括Notice、Warning、Error三个级别的信息。 ?调试输出:显示当前脚本运行时输出的结果,有文本和html两种呈现方式。 主要菜单功能介绍: 文件菜单:新建文件、打开文件、关闭文件,打开项目、关闭项目,选择最近打开的文件或项目等,注意这里不能执行新建项目操作,这个需要在项目窗口才能新建项目; 编辑菜单:除了复制粘贴剪切等常规操作外,还有转换为小写、大写,代码缩进、代码折叠功能,最为称道的应该就是展示片段这个命令了。

相关主题
文本预览
相关文档 最新文档