1 / 36

嵌入式数据库简介

----SQLite. 嵌入式数据库简介. dongqiang@gmail.com. 纲要. SQLite 介绍 SQLite 的发展 SQLite 的优势 SQLite 的缺憾 SQLite 的内部结构 SQLite 数据库的使用 SQLite 的命令行接口 SQLite 命令行使用 SQLite 数据库的编程接口 C/C++ 接口 简单应用 自定义简单函数 自定义聚合函数 自定义排序函数 PERL 接口 SQLite 数据库在 ASTRAL 中的应用 SQLite 在多级关联中的应用 SQLite 在 IPIS 中的应用

sheryl
Download Presentation

嵌入式数据库简介

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. ----SQLite 嵌入式数据库简介 dongqiang@gmail.com

  2. 纲要 SQLite介绍 SQLite的发展 SQLite的优势 SQLite的缺憾 SQLite的内部结构 SQLite数据库的使用 SQLite的命令行接口 SQLite命令行使用 SQLite数据库的编程接口 C/C++接口 简单应用 自定义简单函数 自定义聚合函数 自定义排序函数 PERL接口 SQLite数据库在ASTRAL中的应用 SQLite在多级关联中的应用 SQLite在IPIS中的应用 SQLite在web中的应用

  3. SQLite介绍 SQLite的发展 2000年由D.Richard Hipp开始开发 2001年发布2.0v 2004年发布3.0v(采用了不同的数据文件格式以及编程接口) 目标 易于管理、操作、维护、自定义以及提供易用的编程接口

  4. SQLite介绍 SQLite的优势 内存占用量小 比MySQL(2倍), PostgreSQL(20倍)快 ACID兼容(原子性,一致性,独立性,可持久性),支持视图,子查询,触发器 单个库文件中包含数据库引擎与接口,且其运行不依赖其它库 可以将数据放进单个文件 为C/C++, Perl,PHP等应用提供了接口 免费 允许为SQL命令集动态添加自定义函数(简单函数及聚集函数),而无需重编SQLite库

  5. SQLite介绍 SQLite的 缺点 事务处理并发性 SQLite通过数据库级上的独占性和共享锁来实现独立事务处理,这意味着当多个进程或线程在同一时间可以从数据库读取数据,但是只能有一个可以同时写入,在写入之前,必须获得独占锁,其它的读操作不允许发生。 性能 在创建索引( CREATE INDEX)和删除表( DELTE TABLE)时明显比其它数据库慢 用户管理/安全 数据库的访问是基于操作系统对文件的控制来控制的,不能通过用户来区分数据库中的不同数据库. 举例,将数据库文件去写权限,然后向其中插入或删除数据条目,将提示写失败。但是不能通过数据库本身的来对权限进行设置。 在网上已经有一些SQLite的安全问题的解决方案,但大多数是商业化的,有些提供在整个数据库上的加密,有些提供在数据级别的加密。比如secure SQLite之类。

  6. SQLite的内部结构     在内部,SQLite 由以下几个组件组成:SQL 编译器、内核、后端以及附件。SQLite 通过利用虚拟机和虚拟数据库引擎(VDBE),使调试、修改和扩展 SQLite 的内核变得更加方便。所有 SQL 语句都被编译成易读的、可以在 SQLite 虚拟机中执行的程序集。 1、接口将SQL语句传给SQL编译器 2、SQL编译器选将SQL分解成为Token 3、将Token传递给解析器进行解析 4、由代码生成器生成虚拟机代码 5、由虚拟机执行生成的程序 6、SQLite库在磁盘上以B树形式组织(每个表和索引都有自己单独的B树,所有的B树都保存的同一个文件里面) 7、OS层的操作 大多数的SQL内建函数可以在func.c, date.c里面找到。用户自定义函数编写可以参考这里面的实现。无论内内建函数还是用户自定义函数都是用C的回调方式实现(稍后再做介绍)

  7. SQLite数据库的使用 SQLite命令行接口 SQLite除库本身外,还包含命令行接口,可以在$SQLITE_HOME/bin下发现sqlite/sqlite3, 命令行功能介绍 运行方式:sqlite DBFile 得到提示符sqlite> 运行.help(注意sqlite命令行提供的命令都以”.”开头,可以看到sqlite命令行接口提供下面的功能.

  8. SQLite命令行功能简介 SQLite命令行功能简介 DML/DDL语句的使用和以前一致,不做介绍 .databases 列出数据库文件名 .tables ?PATTERN? 列出?PATTERN?匹配的表名 .import FILE TABLE 将文件中的数据导入的文件中 .dump ?TABLE? 生成形成数据库表的SQL脚本 .output FILENAME 将输出导入到指定的文件中 .output stdout 将输出打印到屏幕 .mode MODE ?TABLE? 设置数据输出模式(csv,html,tcl… .nullvalue STRING 用指定的串代替输出的NULL串 .read FILENAME 执行指定文件中的SQL语句 .schema ?TABLE? 打印创建数据库表的SQL语句 .separator STRING 用指定的字符串代替字段分隔符 .show 打印所有SQLite环境变量的设置 .quit 退出命令行接口

  9. SQLite命令行功能使用 下面举例说明SQLITE命令行的常规使用: • SQLite数据导入 • 创建数据文件 这个文件可能来自其它的其它程序的输出之类,现只我们手功创建下面的数据文件data.txt(用逗号分隔): id, name,gender, age 1,dq,male,24 2,jz,female,27 3.pp,male,26 4,cj,male,28 5,zc,male,25 • 创建数据库表 • 五种数据类型 TEXT,NUMERIC,INTEGER,REAL,NONE • 数据类型的转换 向保存的目标类型转换,如将text保存到integer,则试着将文件转为数字(int或float),如果转换失败,则做为文件保存. • 数据库表创建 shell> sqlite3 test.db sqlite> create table employee( id integer primary key, name text, gender text, age integer );

  10. SQLite命令行功能使用 • 数据导入 sqlite>.import data.txt employee sqlite提示:data.txt line1:expected 4 coloumns of data but found 1; 从经验应该能看出是字符分隔符有问题,先来看看系统用什么样的提示符: .show之后可以看到 separator: “|”,也就是说系统默认的分隔符为”|”面不是”,”,下面修改分隔字符: sqlite>.separator “,” sqlite>.import data.txt employee sqlite> select * from employee where id > 2; sqlite> select * from employee where name > 9999999999999; 上面这句用来说明text>integer(这个和比较字符的内码得到的结果是相同的) • 数据比较 • NULL<INTERGER(REAL)<TEXT<BLOB • 数字之间用数学比较方法比较 • TEXT/BLOB用memcpy()进行比较 • 比较方法是可以自已定义或者重载的(我们将在后面提及中文字串的比较) Ex: sqlite> select id >2, name > ‘dong’, gender=‘male’ from employee; 0,1,1 0,1,0 1,1,1 1,0,1 1,1,1

  11. SQLite命令行功能使用 下面举例说明SQLITE命令行的常规使用: • SQLite数据导出 • 将数据表导出为数据创建脚本 sqlite> .dump employee 上面的命令可以得到数据表相关的SQL语句,为了将输出保存的文件中,执行下面的命令。 sqlite > .output create.sql sqlite > .dump employee sqlite > .output stdout (将输出恢复到标准输出) • 将特定数据导出成数据文件 sqlite > .output data_tmp.html sqlite > select * from employee; sqlite > .mode html employee sqlite > select * from employee; sqlite > .output stdout 上面的几条命令将employee中的数据以html 的格式保存到data_tmp.html中. shell> sqlite test.db “.dump” | sed –e s/dq/dongqiang/ | sqlite3 test2.db 上面的命令行操作将test.db中的dq全部替换为dongqiang然后导入test2.db中 • 创建索引 create index employee_ID on employee( id ); • 创建触发器 create Trigger insert_trigger AFTER INSERT ON employee BEGIN //动作,比如记数,修改时间等 END

  12. SQLite的编程接口简介 • SQLite3 C/C++常见接口 int sqlite3_open(); //数据库的打开,包括文件和内存数据库两种(:memory). int sqlite3_close(); //数据库的关闭 long long int sqlite3_last_insert_rowid(sqlite3*); //最后插入的数据的行号 long long int sqlite3_progress_handler(sqlite3*); //查询的进度,参数为空删除进度信息(实验中) • SQLite3的不同执行方式 • 执行一行或多行SQL语句并在查询结果的每一行上执行回调函数 int sqlite3_exec(); • 动态构造SQL语句 char *sqlite3_mprintf(const char*,...); char *sqlite3_vmprintf(const char*, va_list);//构造语句,由sqlite3_exec执行 int sqlite3_exec_printf();//构造查询语句,并执行 void sqlite3_free(char *z); //释放sqlite3_(v)mprintf分配的内存 • 预编译SQL语句,减少SQL分析的时间 int sqlite3_prepare(); //预编译 int sqlite3_step(sqlite3_stmt*); //执行一次,或者多次 Int sqlite3_reset( sqlite3_stmt*); //重置sqlite3_stmt(来自sqlite3_prepare()) int sqlite3_finalize(sqlite3_stmt *pStmt); //释放 • 利用对sqlite3_exec()的封装,返回所有的查询结果 int sqlite3_get_table(); void sqlite3_free_table(char **result);

  13. SQLite的编程接口简单应用 下面对SQLite的简单使用举例,下面代码去除了对异常处理部分。 • 主函数分析: int main(int argc, char** argv) { sqlite3 * db = NULL; char* zErrMsg = NULL; int rc; sqlite3_open( “:memory:”, &db ); //打开内存数据库 rc = sqlite3_exec(db, “create table employee(id integer primary key, age integer);”, NULL, 0, &zErrMsg);//创建数据库 for( int i= 0; i < 10; i++ ) { statement = sqlite3_mprintf( "insert into employee values(%d, %d);”, NULL, 0, &zErrMsg, rand()%65535, rand()%65535 ); rc = sqlite3_exec( db, statement, NULL, 0 , 0 );//插入数据 sqlite3_free( statement ); } rc = sqlite3_exec(db, “select * from employee;” , callback, 0, &zErrMsg );//查询,并调用回调函数 sqlite3_close(db); }

  14. SQLite的编程接口简单应用 • 回调函数 int calltimes = 0; static int callback(void* notused, int argc, char** argv, char** azColName) { int i; calltimes++; for(i=0; i<argc; i++) { printf(“%s = %s\n”, azColName[i], argv[i] ? argv[i] : “NULL”);//打印出查询结果 } printf(“number %d callback\n”, calltimes); //打印出回调的次数 return 0; }

  15. SQLite自定义函数简介 SQLite最大的特色之一就是可以用户定义函数。用户自定义函数可以像系统内置函数一样可以在注册之后像系统内置函数一样在SQL语句中使用。用户使用自定义函数类似存储过程,方便用户对常见功能的调用,也加快了执行速度。用户自定义函数整体上可以分为两种:简单函数和聚集函数。 • 简单函数(simple function) 简单函数用在任何表达式中,常见的有max(x,y..), min(x,y..), random(*), last_insert_rowid(), length(x),lower(x),upper(x),round(x,y),round(*),substr(x,y,z), typeof(x) • 聚集函数(aggregate function) 聚集函数经常用在select语句中,常见的有avg(x),count(x), count(*), max(x), min(x), sum(x), total(x)   有些函数既是简单函数,又是聚集函数。比如只有一个参数的min()是一个聚集函数,而有多个参数的min()是一个简单函数。 sqlite> select * from employee where id=min( 1, ,2, 3, 4,5); sqlite> select * from employee where id=min(1);//min()是aggragate func作为表达式 SQL Error: misuse of aggregate function main() sqlite> select min(1) from employee;

  16. SQLite的自定义简单函数接口 • 用户自定义函数接口 • int sqlite3_create_function(); 该函数用于注册/删除用户自定义函数。自定义函数传递参数有两种方式,第一种是在注册时用pUserData传入,第二种是在调用已经注册函数时传入参数。 • void (*func)(sqlite3_context*,int,sqlite3_value**); 用户自定义函数的格式,第二个参数是自定函数的参数个数,第三个函数是自定义函数的值。 • void *sqlite3_user_data(sqlite3_context*); 返回用户注册函数时传入的参数void *pUserData。 • int sqlite3_value_type(sqlite3_value*); 用来说明sqlite3_value的数据类型,比如用户自已定义的回调函数的第二个参数的数据类型。 • sqlite3_value_XXXX(sqlite3_value*); 用来返回sqlite3_value所表示的准确值。 • sqlite3_result_XXXX(sqlite3_context*, ...); 用来设置返回值为某一数值的准确拷贝。 对上面的内容更详细的介绍将放在利用自定义接口编程的部分进行说明。对聚合函数及排序函数的接口介绍也推后介绍。

  17. SQLite的自定义函数编程接口 • 注册自定义函数的接口 int sqlite3_create_function( sqlite3 *, //数据库句柄 const char *zFunctionName, //自定义函数的名子 int nArg, //参数个数,-1表示任意个数的参数 int eTextRep, //函数接受的参数数据类型 void *pUserData, //在函数实现中用sqlite_user_data()得到 void (*xFunc)(sqlite3_context*,int,sqlite3_value**), //回调函数,针对简单函数,xStep=NULL, xFinal\NULL void (*xStep)(sqlite3_context*,int,sqlite3_value**), //针对聚集函数,xFun=NULL void (*xFinal)(sqlite3_context*) //针对聚集函数,xFun=NULL ); int sqlite3_create_function16(…);

  18. 自定义函数注册流程 上面的图表说明,无论是用户自定义的函数,还是sqlite内建的函数都利用callback的方式进行注册,用户自定义的函数编写的方式完全可以参照func.c中内建函数的实现方式来实现。

  19. SQLite内建简单函数分析 • 功能:返回传入的第一个参数的byte数 • 参数:argc=1, 表示只能传入一个参数 • 返回值:回调函数的返回值void,但是调用注册函数会返回整数值 static void lengthFunc( sqlite3_context *context, int argc, sqlite3_value **argv) { int len; switch( sqlite3_value_type(argv[0]) ){ //第一个参数的类型 case SQLITE_BLOB: case SQLITE_INTEGER: case SQLITE_FLOAT: { sqlite3_result_int(context, sqlite3_value_bytes(argv[0])); //统计的bytes数 break; } case SQLITE_TEXT: { const unsigned char *z = sqlite3_value_text(argv[0]); for(len=0; *z; z++){ if( (0xc0&*z)!=0x80 ) len++; } //统计字符串的bytes数 sqlite3_result_int(context, len); //设置返回值 break; } default: { sqlite3_result_null(context); //返回NULL break; } } }

  20. 用户自定义简单函数 下面我们实现两个自定义的简单函数: 第一个例子在注册函数时,将用户的数据传入,然后调用自定义函数时,返回传入的值。在下面的例子中,将传入的数据插入到数据库中。 第二个例子在注册函数后,在查询语句中对自定义函数中进行查询,然后将查询的结果进行修正,从202.12.0.32变成http://202.12.0.32的形式返回。 •  例一、 void get_key_func( sqlite3_context * ctx, int dummy1, sqlite3_value ** dummy2 ) { sqlite3_result_int( ctx, *(int *)sqlite3_user_data( ctx ) ) ; } sqlite3_create_function( db->db, "get_key", -1, SQLITE_ANY, &db->key, get_key_func, NULL, NULL ) ; 调用自定义函数的查询语句:INSERT INTO tbl VALUES( get_key(), get_value() ); 上面实现了自定义函数并且将其进行注册,在注册时将db->key做为用户数据传入,每次插入数据前,对db->key的值进行修改,get_key_func()就会返回新的数据,然后将其插入到数据库中。 更为详细的例子将在实际应用部分进行讲解。

  21. 用户自定义简单函数 • 例二、 void host2url_func( sqlite3_context * ctx, int argc, sqlite3_value ** argv ) { if( argc != 1 ) return; char *httpurl=NULL; switch( sqlite3_value_type( argv[ 0 ] ) ) { case SQLITE_NULL: { sqlite3_result_text( ctx, “NULL”, 4, SQLITE_STATIC ); //如果没有传入,返回零 break; } case SQLITE_TEXT: { httpurl = ( char * ) malloc(strlen( sqlite3_value_text( argv[ 0 ] ) ) + 8 ); //分配内存 if ( httpurl == 0 ) return; sprintf( httpurl, “http://%s”, sqlite3_value_text( argv[ 0 ] ) ); sqlite3_result_text( ctx, httpurl, strlen( httpurl ) , SQLITE_TRANSIENT ); //设置返回值 free( httpurl );//释放内存 httpurl = NULL; break; } default: sqlite3_result_text( context, “about:blank”, 11, SQLITE_STATIC ); break; } } sqlite3_create_function( db, “geturl”, 1, SQLITE_ANY, NULL, host2url_func, NULL, NULL ) ; //注册函数 $r = sqlite_exec($db, ‘SELECT geturl(url) FROM host_table;‘, callback, 0, &error ); //查询

  22. 用户自定义简单函数

  23. SQLite的自定义聚合函数接口 • 自定义聚合函数接口 在聚合函数的定义过程中, 在SQLite的自定义简单函数接口一节定义的函数都可以使用,除此之外,还有一些函数可以使用: • sqlite3_aggregate_context( sqlite3_context *, int nBytes );    用来分配一个保存聚合过程状态的结构,在下面的调用中,将返回同样的内存块。该内存在聚合函数调用完成后自动释放。 • void (*xStep)(sqlite3_context*,int,sqlite3_value**); 用户自定义函数的格式,该函数用来统计用户需要的数据,第二个参数是自定函数的参数个数,第三个函数是自定义函数的值。 • void (*xFinal)(sqlite3_context*); 用户自定义函数的格式,用来设置返回值 • 自定义排序函数接口 • sqlite3_create_collation() • sqlite3_create_collation16() 用来创建一个用来排序的函数(不同与简单函数和聚合函数的注册) • void (*xCompare)(void *, int, const void *, int , const void *); 用户自定义函数的格式,第二个参数是自定函数的参数个数,第三个函数是自定义函数的值。

  24. SQLite内建聚合函数分析   聚合函数与简单函数有一些不同。简单函数只有一个回调函数,但是聚合函数有两个回调函数。 struct CountCtx { i64 n; //64bit的整数 }; typedef struct CountCtx CountCtx; //用于记录count()的状态信息的结构 下面两个函数是count()的实现,countStep()用于统计,countFinialize()用于设置返回结果。 static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv) { CountCtx *p; p = sqlite3_aggregate_context(context, sizeof(*p)); if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0])) && p ){ p->n++; //改变统计值 } } static void countFinalize(sqlite3_context *context){ CountCtx *p; p = sqlite3_aggregate_context(context, 0); sqlite3_result_int64(context, p ? p->n : 0); //设置返回结果64bit }

  25. 用户自定义聚合函数   自定义聚合函数的代码主要是两个回调函数的编写以及聚合函数的注册,能过前面的内建聚合函数的分析,我们总结出聚合函数定义的基步骤。 基本步骤如下: • 定义自己的用的聚合函数状态结构 • 利用sqlite3_aggregate_context( ctx, sizeof( struct custom_agg ) )分配状态结构空间 • xStep()的调用会发生很多次,在查询结果的每一行上都运行xStep()进行数据处理,比如累加,计数。 • 在XFinal()中,利用sqlite3_aggregate_context( ctx, 0 )得到状态结构,并且设置返回值。 • 利用sqlite3_create_func()注册聚合函数 • 在sql语句中调用聚合函数 在这里不再给出具体实现,可以参考前面简单函数的实现以及内建聚合函数的实现来编写。

  26. SQLite内部排序函数分析 • 内建排序函数 从前面接口部分的介绍我们可以看到注册一个排序函数是用sqlite3_create_collation()方法,该方法会调用createCollation()来注册排序函数。在main.c里面,我们可以看到在数据库打开完成之后,马上增加注册了下面几个比较函数: createCollation(db, "BINARY", SQLITE_UTF8, 0, binCollFunc); createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc); createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc) ; createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc);

  27. 用户自定义排序函数 • 用户自定义排序函数 如果在数据库中存在一列,该列的内容全部都是中文,我们想以中文的拼音对查询结果进行排序,那么上面预定义的几种排序方法是不可行的,因此,我们需要自己定义一个排序函数。 int pinyin_cmp( void *NotUsed, int nKey1, const void *pKey1,//比较的字符数,比较的指针 int nKey2, const void *pKey2) { int n = nKey1 < nKey1 ? nKey1 : nKey2; return pinyin_strncmp(pKey1, pKey2, n + 1);//中文比较函数 }   安装比较函数时要注意,因为我们实现的比较函数是针对UTF-16的,所以名字要用UTF-16编码。但是由于linux下默认的wchar_t是32位的,不能直接用”pinyin”的方式把ANSI字符串转换成UTF-16字符串,只能按下列方式。 unsigned short zName[] = {'p', 'i', 'n', 'y', 'i', 'n', 0}; sqlite3_create_collation16(db, zName, SQLITE_UTF16, 16, pinyin_cmp); select * from person order by name collate pinyin;

  28. SQLite自定义函数调用关系图 SQLite自定义函数的使用到此为至,现在让我们来看看系统到底是怎么样来注册以及调用自定义函数。 下面的例子我们对sqlite3_prepare()和sqlite3_step()两个函数的流程做一个简单的分析。

  29. 自定义函数调用关系图

  30. SQLite的编程PERL接口 Perl已经支持sqlite3,为了使用perl访问sqlite3,首先要安装DBD::SQLite。可以用下面的命令在CPAN上进行安装: #perl –MCPAN –e shell #cpan> install DBI #cpan > install DBD::SQLite   也可以自己下载源码,然后进行编译,编译完成后将下面的目录树移动到自己想要放置的地方。

  31. SQLite的PERL示例

  32. SQLite数据库应用 在多级关联中动态创建使用索引 多级关联中数据库是动态进行创建,索引也是在数据库的创建过程中进行创建,而sqlite中索引的创建明显比其它的数据库慢,所以大量数据插入的速度相当慢。 在多级关联使用DROP TABLE 因为sqlite数据库中delete操作是一相当慢的操作,因些在数据库使用的过程中,每次要清空数据库表时,直接将数据库删除,再重新创建新的数据库表。 在多级关联中为SQL命令集定义函数 创建多个自定义函数,并结合SQL语句预编译的方式加快数据插入的速度。 在IPIS中预先创建索引 ipis中的whois数据库内部自建了索引,加快了数据查询的速度。

  33. 参考 http://www.sqlite.org (Sqlite英文官方网) http://www.sqlite.com.cn (Sqlite中文网) http://souptonuts.sourceforge.net/readme_sqlite_tutorial.html (SQLite tutorial) http://www.sqlite.com.cn/MySqlite/4/293.Html (SQLite研究自定义函数) http://blog.csdn.net/absurd(中文排序研究) SQLite源码 IPIS源码 多级关联源码 谢谢!

  34. 问题解答 • 问题一,聚合函数min(x)问题解释SQLite version 3.3.6Enter ".help" for instructionssqlite> .schemaCREATE TABLE host_table( host_id integer primary key, desc text );sqlite> select * from host_table;1|192.168.1.1982|192.168.1.883|192.168.1.994|192.168.1.1065|192.168.1.100sqlite> select host_id from host_table;12345sqlite> select min( host_id ) from host_table;1上面的的过程用来说明聚合函数min(host_id),是针对列来操作的。即min(host_id)求出的是所有该列的值的最小值。

  35. 问题解答 • 问题二、简单函数与聚合函数的区别简单函数的操作对象是行上的单个字段。聚合函数的操作对象是指定的列。问题四、内存数据库的打开    可以同时打开多个内存数据库,并不像打开文件那样是创建一个文件的多个句柄。利子程序在附件中可以看到 • 问题三、数据库大小的问题    支持2T大小的数据库文件   字符串与Blob的大小只与可用的内存大小有关 • 问题四:sqlite3数据导出的模式有下面几种csv      Comma-separated values             column   Left-aligned columns.  (See .width)             html     HTML <table> code             insert   SQL insert statements for TABLE             line     One value per line             list     Values delimited by .separator string             tabs     Tab-separated values             tcl      TCL list elements

  36. 问题解答 • 问题五.rowid相关问题解释sqlite> select last_insert_rowid();   //表中虽然有数,但是rowid在没有插入数据时为零0sqlite> insert into host_table values( 7, "192.168.1.68" );      //自己指定主键的值sqlite> select * from host_table where rowid= last_insert_rowid();   //此时rowid()是我们自己设置的值77|192.168.1.68sqlite> insert into host_table( desc ) values ( "192.168.1.70" );   //如果不指定主键,主键自增长,last_insert_rowid()返回系统设置的值sqlite> select * from host_table where rowid= last_insert_rowid();8|192.168.1.70sqlite> 在创建数据表时,指定primary key通常仅仅只是在相应于栏位创建一个单键索引,但是如果primary key是应用在一个数据类型为INTEGER的数据栏上,那么这个栏在内部被做为B树的索引键。如果数据表没有一个INTEGER PRIMARY KEY的栏位,那么B树将自动产生B树的键。也就是如果没有id这个键位的话,sqlite会有另一个列,其值表现为rowid。在SQLite中,每一个表中的表一行都一个一rowid,在一个表里面,rowid是唯一的,在sqlite2.8中,rowid是32bit,在3.0后,rowid用 64bit来表示。可以用rowid, _rowid, oid来访问,如果你自己的表里面有一个rowid,那么,就使用你自己指定的rowid,而不是内的rowid.通常新插入的行rowid是最大的 rowid+1,如果最大的rowid达到最大,那么,sqlite会随机取一个没有用的rowid。这也就是说,只要不删、不指定最大的rowid,那么rowid就是自动增加的,删除条目不会导致rowid的减小,所以如果表里面有100条数据,rowid等于100,全删后,rowid不会变化。 AUTOINCREMENT关键字保证rowid的持续增长,如果达到最大值,则返回SQLITE_FULL的错误。last_insert_rowid ()

More Related