Chinaunix首页 | 论坛 | 博客
  • 博客访问: 555281
  • 博文数量: 99
  • 博客积分: 5015
  • 博客等级: 大校
  • 技术积分: 1209
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-28 23:08
文章存档

2011年(7)

2010年(6)

2009年(86)

我的朋友

分类: 数据库开发技术

2009-06-19 16:02:48

***************************************
* 嵌入式数据库sqlite在LPC22XX上的应用 *
***************************************
    2008/03/28  asdjf@163.com  

    《ecos增值包》已经提供了完整的BSD协议栈、web server、文件系统,在此基础上我们实现了动态CGI网页,如果再加入数据库功能,那么就可以非常完美地实现和在大型托管服务器上一样的功能。例如:可以把我们的包括论坛、留言簿、下载管理、文章管理的ASP+ACCESS/SQL SERVER型动态网站做到EASYARM2200/SMARTARM2200开发板上。当然,除了实现论坛,其他各种非数值型应用也非常适合用数据库实现。如:地图数据、电话簿、歌曲目录,甚至有人写了个程序,自动记录电池状态,写进SQLite数据库中再做统计......发挥你的想象力,相信你一定能找出更多适合使用数据库实现的项目实例。
    
    图1 yy.db数据库结构,表、字段名称、类型、缺省值等。
图2 yy.db数据库内容浏览
图3 yy.db数据库执行SQL命令结果
-----------------------
     为什么要使用数据库呢?
    -----------------------
    我个人的理由就是:我喜欢用简单统一的SQL语句实现复杂的数据处理。
    
    回顾计算机发展的历史,数据处理经历了:人工管理、文件管理和数据库管理三个阶段。早期的数据和程序不具有独立性,一组数据对应一组程序,如果数据存储发生了一些变化,就必须修改程序,而且各种程序中的数据会有大量重复。现代的数据库系统比文件系统更加先进:1、数据是结构化的,相互之间存在关联,冗余度小,从而更能适应大量数据管理的客观需要;2、数据可以由多个用户共享,数据库保证其完整性、安全性和并发性;3、数据具有独立性,当存储结构改变时,逻辑结构可以不变,进而,对应的应用程序也不必修改。这使得应用程序的维护工作大大简化。
    
    数据库比普通文件更适合于表达数据量大,且在数据之间存在着复杂联系的应用系统。一般,关系数据库常用非过程化的命令或语言,不仅使应用程序的长度较传统的应用系统大为缩短,而且明显提高了应用程序的开发效率。
    
    使用数据库肯定会带来很多好处,尤其是应用程序的开发速度大大提高了,稳定性也好,不过,嵌入式系统内存和性能受限,不能直接使用桌面系统上现成的大型数据库,因此,现在出现了很多轻量级,速度很快的嵌入式数据库,sqlite就是其中一个不错的选择。
    
    ------------
     sqlite简介
    ------------
    SQLite是D.Richard Hipp用C语言编写的开源嵌入式数据库引擎。它是完全独立的,不具有外部依赖性。它是作为PHP V4.3中的一个选项引入的,构建在PHP V5中。SQLite支持多数SQL92标准,可以在所有主要的操作系统上运行,并且支持大多数计算机语言。SQLite还非常健壮。其创建者保守地估计SQLite可以处理每天负担多达10000次点击率的Web站点,并且SQLite有时候可以处理10倍于上述数字的负载。

    在功能上,SQLite对SQL92标准的支持包括索引、限制、触发和查看。SQLite不支持外键限制,但支持原子的、一致的、独立和持久 (ACID) 的事务。SQLite支持大小高达2TB的数据库,每个数据库完全存储在单个磁盘文件中。这些磁盘文件可以在不同字节顺序的计算机之间移动。这些数据以B+树(B+tree)数据结构的形式存储在磁盘上。SQLite 根据该文件系统获得其数据库权限。
    
    ----------------
     sqlite使用手册
    ----------------
    数据库的大量操作一般是对数据的存储、查询、检索、修改以及安全保护等等,SQL语言抽象了这些处理请求为非过程化的命令或语言,使得数据处理过程变得简单统一。

建立数据库档案

用sqlite3建立数据库的方法很简单,只要在shell下键入(以下$符号为shell提示号,请勿键入):

$ sqlite3 foo.db

如果目录下没有foo.db,sqlite3就会建立这个数据库。sqlite3并没有强制数据库档名要怎么取,因此如果你喜欢,也可以取个例如foo.icannameitwhateverilike的档名。


在sqlite3提示列下操作

进入了sqlite3之后,会看到以下文字:

SQLite version 3.1.3Enter ".help" for instructionssqlite>

这时如果使用.help可以取得求助,.quit则是离开(请注意:不是quit)


SQL的指令格式

所以的SQL指令都是以分号(;)结尾的。如果遇到两个减号(--)则代表注解,sqlite3会略过去。


建立资料表

假设我们要建一个名叫film的资料表,只要键入以下指令就可以了:

create table film(title, length, year, starring);

这样我们就建立了一个名叫film的资料表,里面有name、length、year、starring四个字段。

这个create table指令的语法为:

create table table_name(field1, field2, field3, ...);

table_name是资料表的名称,fieldx则是字段的名字。sqlite3与许多SQL数据库软件不同的是,它不在乎字段属于哪一种资料型态:sqlite3的字段可以储存任何东西:文字、数字、大量文字(blub),它会在适时自动转换。


建立索引

如果资料表有相当多的资料,我们便会建立索引来加快速度。好比说:

create index film_title_index on film(title);

意思是针对film资料表的name字段,建立一个名叫film_name_index的索引。这个指令的语法为

create index index_name on table_name(field_to_be_indexed);

一旦建立了索引,sqlite3会在针对该字段作查询时,自动使用该索引。这一切的操作都是在幕后自动发生的,无须使用者特别指令。


加入一笔资料

接下来我们要加入资料了,加入的方法为使用insert into指令,语法为:

insert into table_name values(data1, data2, data3, ...);

例如我们可以加入

insert into film values ('Silence of the Lambs, The', 118, 1991, 'Jodie Foster');insert into film values ('Contact', 153, 1997, 'Jodie Foster');insert into film values ('Crouching Tiger, Hidden Dragon', 120, 2000, 'Yun-Fat Chow');insert into film values ('Hours, The', 114, 2002, 'Nicole Kidman');

如果该字段没有资料,我们可以填NULL。


查询资料

讲到这里,我们终于要开始介绍SQL最强大的select指令了。我们首先简单介绍select的基本句型:

select columns from table_name where expression;

最常见的用法,当然是倒出所有数据库的内容:

select * from film;

如果资料太多了,我们或许会想限制笔数:

select * from film limit 10;

或是照着电影年份来排列:

select * from film order by year limit 10;

或是年份比较近的电影先列出来:

select * from film order by year desc limit 10;

或是我们只想看电影名称跟年份:

select title, year from film order by year desc limit 10;

查所有茱蒂佛斯特演过的电影:

select * from film where starring='Jodie Foster';

查所有演员名字开头叫茱蒂的电影('%' 符号便是 SQL 的万用字符):

select * from film where starring like 'Jodie%';

查所有演员名字以茱蒂开头、年份晚于1985年、年份晚的优先列出、最多十笔,只列出电影名称和年份:

select title, year from film where starring like 'Jodie%' and year >= 1985 order by year desc limit 10;

有时候我们只想知道数据库一共有多少笔资料:

select count(*) from film;

有时候我们只想知道1985年以后的电影有几部:

select count(*) from film where year >= 1985;

(进一步的各种组合,要去看SQL专书,不过你大概已经知道SQL为什么这么流行了:这种语言允许你将各种查询条件组合在一起──而我们还没提到「跨数据库的联合查询」呢!)


如何更改或删除资料

了解select的用法非常重要,因为要在sqlite更改或删除一笔资料,也是靠同样的语法。

例如有一笔资料的名字打错了:

update film set starring='Jodie Foster' where starring='Jodee Foster';

就会把主角字段里,被打成'Jodee Foster'的那笔(或多笔)资料,改回成Jodie Foster。

delete from film where year < 1970;

就会删除所有年代早于1970年(不含)的电影了。


其他sqlite的特别用法

sqlite可以在shell底下直接执行命令:

sqlite3 film.db "select * from film;"

输出 HTML 表格:

sqlite3 -html film.db "select * from film;"

将数据库「倒出来」:

sqlite3 film.db ".dump" > output.sql

利用输出的资料,建立一个一模一样的数据库(加上以上指令,就是标准的SQL数据库备份了):

sqlite3 film.db < output.sql

在大量插入资料时,你可能会需要先打这个指令:

begin;

插入完资料后要记得打这个指令,资料才会写进数据库中:

commit;
    
    ----------
     应用范例
    ----------
    下面是一个简单范例,用于说明如何用C/C++和sqlite函数库接口。
    
#include
#include

static int callback(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  for(i=0; i     printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
  }
  printf("\n");
  return 0;
}

int main(int argc, char **argv){
  sqlite3 *db;
  char *zErrMsg = 0;
  int rc;

  if( argc!=3 ){
    fprintf(stderr, "Usage: %s DATABASE SQL-STATEMENT\n", argv[0]);
    exit(1);
  }
  rc = sqlite3_open(argv[1], &db);
  if( rc ){
    fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
    sqlite3_close(db);
    exit(1);
  }
  rc = sqlite3_exec(db, argv[2], callback, 0, &zErrMsg);
  if( rc!=SQLITE_OK ){
    fprintf(stderr, "SQL error: %s\n", zErrMsg);
    sqlite3_free(zErrMsg);
  }
  sqlite3_close(db);
  return 0;
}

注解:
    sqlite3_open()打开数据库“/home/testdb.db”;
    sqlite3_exec()执行针对该数据库的SQL命令;
    sqlite3_close()关闭数据库连接。

运行make编译测试程序,生成的程序大小约300KB:

接着将测试程序下载到目标板,测试运行结果如下:
# /home/sqlitetest /home/testdb.db "CREATE TABLE my_table(id int, name varchar(20))"
# /home/sqlitetest /home/testdb.db "INSERT INTO my_table values(1, 'jianglj')"
# /home/sqlitetest /home/testdb.db "INSERT INTO my_table values(2, 'Hily Jiang')"
# /home/sqlitetest /home/testdb.db "SELECT * FROM my_table"
id = 1
name = jianglj

id = 2
name = Hily Jiang

#

    ----------
     论坛实例
    ----------
    论坛数据库的建立可以使用DOS下的命令行接口数据库管理工具。
    
    例如:
    
1、创建新的数据库和表

c:\t>sqlite3 c:\t\yy.db
SQLite version 3.2.1
Enter ".help" for instructions
sqlite> create table mytable(name varchar(40), age smallint);
sqlite> insert into mytable values('Nils-Erik',23);
sqlite> select * from mytable;
Nils-Erik|23
sqlite>

然后,可以再次打开该数据库,列出它的表和架构,并继续进行插入和删除值的操作。

2、列出表和架构

c:\t>sqlite3 c:\t\yy.db
SQLite version 3.2.1
Enter ".help" for instructions
sqlite> .tables
mytable
sqlite> select * from mytable;
Nils-Erik|23
sqlite> .schema
CREATE TABLE mytable(name varchar(40), age smallint);
sqlite>

    图1、图2、图3是通过GUI图形数据库管理工具查看yy.db的效果。

    通过命令行/GUI数据库管理工具,我们可以在PC机上创建一个论坛数据库,就象创建access数据库那样,把表格构造好,这样一个空白的数据库bbs.db就做好了,然后将其保存在CF/SD卡上,在CGI程序里使用sqlite的C/C++接口操作此数据库,就可以把论坛移植到EASYARM2200/SMARTARM2200开发板上了。本站论坛的数据关系不在此详细列出,感兴趣的朋友可以参照上的论坛自行实现,或者参照开源的ASP代码做个留言板也不错。

阅读(3622) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~