您好,欢迎访问一九零五行业门户网

嵌入式数据库比较(SQLite Birkeley DB Firebird)

嵌入式数据库与非嵌入式数据库的差别,在于运行模式的差别。并不是运行在嵌入式手持设备上的数据库就是嵌入式数据库,那种数据库我们通常称做嵌入式移动数据库。理论上讲,嵌入式设备一样可以运行网络数据库的服务端程序。 嵌入式数据库是指运行在本机上、不
嵌入式数据库与非嵌入式数据库的差别,在于运行模式的差别。并不是运行在嵌入式手持设备上的数据库就是嵌入式数据库,那种数据库我们通常称做嵌入式移动数据库。理论上讲,嵌入式设备一样可以运行网络数据库的服务端程序。
      嵌入式数据库是指运行在本机上、不用启动服务端的轻型数据库,它与应用程序紧密集成,被应用程序所启动,并伴随应用程序的退出而终止。
      从这个意义上讲,似乎所有单机数据库都可以算嵌入式数据库,比如access,paradox,dbf等等,因为它们都不用启动数据库服务器即可使用。然 而,我们通常不将上述数据库归入嵌入式数据库,而只将它们归入“桌面数据库”,甚至“文件型数据库”,因为这些数据库的完备性、存储容量及性能方面存在较 大的缺陷。
      嵌入式数据库支持的数据都是tb文件级别,更由于嵌入式数据库具备高性能的特点,可以预测,单机数据库的未来将是嵌入式数据库的天下。
嵌入式数据库三雄
     目前,嵌入式数据库市场主要由三个产品分割:sqlite,birkeley db,firebird嵌入服务器版,巧的是,这三个数据库产品都是开源软件。
sqlite    主页:http://www.sqlite.org
sqlite诞生于2000年5月,这几年增长势头迅猛无比,目前版本是3.3.8。
sqlite的特点如下:
1、无需安装配置,应用程序只需携带一个动态链接库。
2、非常小巧,for windows 3.3.8版本的dll文件才374kb。
3、acid事务支持,acid即原子性、一致性、隔离性、和持久性(atomic、consistent、isolated、和 durable)。
4、数据库文件可以在不同字节顺序的机器间自由的共享,比如可以直接从windows移植到linux或mac。
5、支持数据库大小至2tb。
berkeley db    主页:http://www.oracle.com/database/berkeley-db/index.html
berkeley db是由美国sleepycat software公司开发的一套开放源码的嵌入式数据库的程序库,它于1991年发布,号称“为应用程序开发者提供工业级强度的数据库服务”,可谓是老牌悍将。sleepycat现已被甲骨文(oracle)公司收购。
berkeley db的特点如下:
1、嵌入式,无需安装配置。
2、为多种编程语言提供了api接口,其中包括c、c++、java、perl、tcl、python和php等等。
3、轻便灵活。它可以运行于几乎所有的unix和linux系统及其变种系统、windows操作系统以及多种嵌入式实时操作系统之下。
4、可伸缩。它的database library才几百kb大小,但它能够管理规模高达256tb的数据库。它支持高并发度,成千上万个用户可同时操纵同一个数据库。
firebird 嵌入服务器版(embedded server)   主页:http://www.firebirdsql.org
从interbase开源衍生出的firebird,充满了勃勃生机。虽然它的体积比前辈interbase缩小了几十倍,但功能并无阉割。为了体现firebird短小精悍的特色,开发小组在增加了超级服务器版本之后,又增加了嵌入版本,最新版本为2.0。
firebird的嵌入版有如下特色:
1、数据库文件与firebird网络版本完全兼容,差别仅在于连接方式不同,可以实现零成本迁移。
2、数据库文件仅受操作系统的限制,且支持将一个数据库分割成不同文件,突破了操作系统最大文件的限制,提高了io吞吐量。
3、完全支持sql92标准,支持大部分sql-99标准功能。
4、丰富的开发工具支持,绝大部分基于interbase的组件,可以直接使用于firebird。
5、支持事务、存储过程、触发器等关系数据库的所有特性。
6、可自己编写扩展函数(udf)。
嵌入式数据库特性对比
产品名称 sqlite   berkeley db   firebird嵌入服务器版
当前版本: 3.3.8、4.5.20、2.0
速度:最快、快、快
稳定性:好、好、好
数据库容量:2tb、256tb、64tb
sql支持:大部份sql- 92、不支持、完全sql-92与大部份sql-99
win32平台下最小体积:374kb、840kb、3.68mb
数据操纵:sql、仅应用程序接口、sql
开发接口:c, c++, php, java, delphi, python .net(有些是第三方厂商开发的)
从 以上对比中,我们可以看到,最短小精悍的是sqlite,它的性能也是最高的,berkeley db比较特殊,因为它不是用sql语言来操纵数据的,firebird嵌入版的体积对比之下显得稍大了些,但它对关系数据库特性的支持是最好的,如果要考 虑到今后或许要将数据库升级成网络版本,就要选firebird了。
嵌入式数据库开发布署举例
例1、用delphi开发基于sqlite的单机版应用程序
因为sqlite自带c、c++、java接口,所以我这里举用delphi开发的例子。
使用组件:第三方组件asqlite。
下载地址:http://www.aducom.com/cen/download.php?list.2
选择后边是.d的,就是for delphi的组件。
下载解压之后,即可开始用delphi打开dpk组件包编译安装。
如果您的delphi版本比较高,比如是delphi 2006,那么就编译asqlite3.dpk与asqlite3pkg.dpk,之后再安装asqlite3pkg.dpk包即可。
然后在delphi组件面板里可以看得到asqlite组件,如图:
现在就可以用它开发你的程序了,基于sqlite小巧的原因,特别推荐你在布署远程应用时用它,比如监控啊,木马啊什么的。
ok,为了使我们的例子更详细,下面讲讲怎么用asqlite组件创建、连接数据库,并建立一个数据表。
新 建一个窗体,放一个tasqlite3db,命名为db1,将它的database(数据库)设为test.sqb,放一个 tasqlite3query,命名为query1,将它的connection指向db1,然后放入两个按钮,第一个按钮的作用是创建或连接数据库,第 二个按钮的作用是建立数据表。
如下图:
“连接”按钮事件的代码如下:
db1.open;
执行完这条语句之后,如果应用程序当前目录下不存在test.sqb文件,则自动创建并连接它。
“建表”按钮事件的代码如下:
query1.starttransaction;
try
query1.close;
query1.sql.text:='create table student(sname vchar(30),age integer)';
query1.execsql;
query1.commit;
except
query1.rollback;
end;
执行完这些语句之后,在test.sqb数据库里将创建数据表student。
现在,请将您下载的sqlite的动态链接库sqlite3.dll文件复制到应用程序目录下。
之后,可正常运行。
布署时,也应将sqlite3.dll文件一起打包。
例2、使用c++语言开发基于firebird嵌入版的应用程序。
由于firebird衍生于interbase,所以delphi对它的支持最好,ibx,dbx,fibplus等都可以直接使用它,只要注意将接口文件改为fbembed.dll即可。在此不再多言。
对于c++这种最通用的语言,我们有一个更好的组件可以选择:ibpp。
ibpp主页:http://www.ibpp.org/
ibpp是用c++封装的firebird接口,最新版本2.5.2.2。
只要在c++里引用all_in_one.cpp文件,就可以使用它的功能。
可 以用ibpp:database类连接数据库,用ibpp::transaction类控制事务,ibpp::statement类可以获取数据集。下面 展示一段代码,功能为:先连接d:\demo.fdb文件,然后从student表里选择所有记录,遍历所有记录之后,显示最后一条记录的sn与 sname字段。为了使演示更直观,省去了异常处理。
示例代码:
#define ibpp_windows   //运行于windows平台的预先声明
#include ibpp/all_in_one.cpp
……
ibpp:database db1;
db1=ibpp:databasefactory(,d:/demo.fdb,sysdba,masterkey);
db1->connect();
ibpp::transaction tr1=ibpp::transactionfactory(db1,ibpp::amwrite,
ibpp::ilconcurrency,ibpp::lrwait, ibpp::tfnoautoundo);
tr1->start();
ibpp::statement st1=ibpp::statementfactory(db1,tr1);
st1->prepare(select * from student);
st1->execute();
std::string sn,sname;
st1->fetch();
st1->get(1,sn);
st1->get(2,sname);
tr1->commit();
label1->caption=sn.c_str();
label2->caption=sname.c_str();
最后2行语句为显示结果的,不同开发平台应该使用不同的方法演示,请勿直接复制源代码。
布署时,还应该带上如下文件:fbembed.dll,ib_util.dll,icudt30.dll,icuin30.dll,icuuc30.dll,为了更通用,还可以带上vc++ 7.1的运行库msvcp71.dll,msvcr71.dll两个文件。
工程实例
http://hi.baidu.com/cokee/blog/item/7ac5bc013a5cb50a1d9583da.html
2010年05月25日 星期二 13:07
因 为项目中要用到嵌入式数据库,现在网上找了一些资料了解了一下嵌入式数据。在http://blog.csdn.net/love_study /archive/2009/04/07/4053644.aspx中讲得蛮清楚。综合各自特点,最后决定选用sqlite。借鉴http: //www.codeproject.com/kb/database/cppsqlite.aspx,自己写了一个小例子,实现了创建数据库,创建表, 添加记录,删除记录,查询记录,修改记录等功能。
#include sqlite3.h
#include
#include
#pragma comment(lib, sqlite3.lib)
const char* g_cadbname = c:\\sqlitedb.db;
const char* g_catabename = tb_test;
sqlite3* g_pdb = null;
file* g_pfile = stdout;
char* g_caerrormsg = null;
#define group_num 100
char g_groupsqlstr[group_num][256] = {0};
int test1();   //测试创建一个新数据库,并向此数据库添加表,对表中的记录进行增,删,改,查。
int main(int argc, char* argv[])
{
test1();
system(pause);
return 0;
}
int test1()
{
int ret = sqlite_error;
//创建数据库
remove(g_cadbname);
ret = sqlite3_open(g_cadbname, &g_pdb);
if (!g_pdb)
{
fprintf(g_pfile, 创建数据库失败: %d\n, ret);;
return -1;
}
else
{
fprintf(g_pfile, 创建数据库: %s 成功\n, g_cadbname);
}
char sqlstr[512];
//创建表
sprintf(sqlstr, create table %s(fd_id int, fd_name char(20)), g_catabename);
ret = sqlite3_exec(g_pdb, sqlstr, null, null, &g_caerrormsg);
if (ret != sqlite_ok)
{
fprintf(g_pfile, 创建表失败:%d\n, ret);
return -1;
}
else
{
fprintf(g_pfile, 创建表: %s 成功%\n, g_catabename);
}
//插入数据
int i = 0;
for(; i {
sprintf(g_groupsqlstr[i], insert into %s values(%d, '%d'), g_catabename, i, i);
}
clock_t starttime = clock();
sqlite3_exec(g_pdb, begin transaction;, null, null, &g_caerrormsg);
for(i = 0; i {
sqlite3_exec(g_pdb, g_groupsqlstr[i], null, null, &g_caerrormsg);
}
sqlite3_exec(g_pdb, commit trans;, null, null, &g_caerrormsg);
clock_t endtime = clock();
fprintf(g_pfile, 插入%d条数据,花费%d毫秒\n, group_num, endtime - starttime);
//查询数据条数
const char* ptail;
sqlite3_stmt* stmt;
sprintf(sqlstr, select count(*) from %s, g_catabename);
ret = sqlite3_prepare(g_pdb, sqlstr, strlen(sqlstr), &stmt, &ptail);
if (ret != sqlite_ok)
{
fprintf(g_pfile, 查询记录条数失败);
return -1;
}
else
{
int recordcount = 0;
ret = sqlite3_step(stmt);
if (ret != sqlite_row)
{
fprintf(g_pfile, 查询记录失败: %d, ret);
return -1;
}
recordcount = sqlite3_column_int(stmt, 0);
fprintf(g_pfile, 共有%d条记录\n, recordcount);
}
sqlite3_finalize(stmt);
//列出表中所有的数据
fprintf(g_pfile, %10s%10s\n, id, name);
sprintf(sqlstr, select fd_id, fd_name from %s, g_catabename);
ret = sqlite3_prepare(g_pdb, sqlstr, strlen(sqlstr), &stmt, &ptail);
if (ret != sqlite_ok)
{
fprintf(g_pfile, 查询记录条数失败);
return -1;
}
else
{
int id;
char name[256];
do 
{
ret = sqlite3_step(stmt);
if (ret == sqlite_done)
{
break;
}
else if(ret != sqlite_row)
{    
fprintf(g_pfile, 查询记录失败: %d, ret);
return -1;
}
id = sqlite3_column_int(stmt, 0);
strcpy(name, (const char*)sqlite3_column_text(stmt, 1));
fprintf(g_pfile, %10d%10s\n, id, name);
} while(true);
}
sqlite3_finalize(stmt);
//修改数据
starttime = clock_t();
sprintf(sqlstr, update tb_test set fd_name = 'new name' where fd_id > 40 and fd_id endtime = clock_t();
ret = sqlite3_exec(g_pdb, sqlstr, null, null, &g_caerrormsg);
if (ret != sqlite_ok)
{
fprintf(g_pfile, 修改失败:%d\n, ret);
return -1;
}
int rowseffect = sqlite3_changes(g_pdb);
fprintf(g_pfile, 修改了%d条数据, 消耗%d毫秒\n, rowseffect, endtime - starttime);
//删除数据
starttime = clock_t();
sprintf(sqlstr, delete from tb_test where fd_id > 40 and fd_id endtime = clock_t();
ret = sqlite3_exec(g_pdb, sqlstr, null, null, &g_caerrormsg);
if (ret != sqlite_ok)
{
fprintf(g_pfile, 删除失败:%d\n, ret);
return -1;
}
rowseffect = sqlite3_changes(g_pdb);
fprintf(g_pfile, 删除了%d条数据, 消耗%d毫秒\n, rowseffect, endtime - starttime);
sqlite3_close(g_pdb);
return 0;
}
(#)
其它类似信息

推荐信息