您的位置:首页 > 博客中心 > 数据库 >

linux程序设计——数据库(第七章)

时间:2022-03-14 10:53

7.3 数据库

这篇为linux的dbm数据库,代码在。可以使用文件来存储数据,为什么还需要数据库呢?因为在有些情况下,数据库的特性提供了解决问题的更好的办法。与使用文件来存储数据相比,使用数据库有如下两方面的优势:
1.可以存储长度可变的数据记录,这对平面的、非结构化的文件来说实现起来有点困难
2.数据库使用索引来有效地存储和检索数据。这样做的一个显著优点是这个索引不必要非得是一个简单的记录号——这在平面文件中很容易实现,它可以是一个任意的字符串。

7.3.1 dbm数据库

所有版本的linux以及大多数UNIX版本都随系统带有一个基本的、但是却非常高效的数据存储例程集,它被成为dbm数据库。dbm数据库适合与存储相对静态的索引化数据
1.dbm简介
尽管一些免费的关系型数据库,例如MYSQL和PostgreSQL使用越来越广泛,dbm数据库仍然在linux中扮演这一个重要的角色。那些使用RPM的linux发行版本,就是用dbm来存储已安装软件包的信息。与更加完整的数据库产品如MySQL相比,dbm的优势在于它是一个轻量级的软件,而且非常容易被编译进一个可发布的二进制文件中,因为它无需安装独立的数据库服务器。
dbm数据库可以使用索引来存储可变长的数据结构,然后通过索引或顺序扫描数据库来检索结构。dbm数据库适用于处理那些被频繁访问但却很少被更新的数据,因为它们创建数据项时非常缓慢,而检索时非常快
2.获得dbm
大多数主流的linux发行版都会默认安装gdbm,但在一些发行版中,可能需要使用软件管理器来安装相应的开发库,例如在ubuntu中,可能需要安装libgdbm-dev软件包。
3.故障解决和重装dbm
如果系统已经安装了gdbm,并且在默认情况下就支持了ndbm兼容模式,则需要执行如下操作:
1-在C源文件中包含头文件ndbm.h
2-使用编译行选项-I/usr/include/gdbm来包含头文件目录/usr/include/gdbm
3-使用编译行选项-lgdbm链接gdbm库
如果这样不行,则需要在链接主函数库之前链接兼容库,如下所示:
1-在C源文件中包含头文件gdbm-ndbm.h而不是ndbm.h
2-使用编译行选项-I/usr/include/gdbm包含头文件目录/usr/include/gdbm
3-使用编译行选项-lgdbm_compat -lgdbm链接其他的gdbm兼容库

7.3.2 dbm例程

dbm由头文件和库文件组成,而库文件必须在程序被编译时链接进来。在编译行中使用选项-lgdbm来链接这个实现。
dbm数据库的基本元素是需要存储的数据块以及与它关联的在检索数据时用作关键字的数据块。每个dbm数据块必须针对每个要存储的数据块有一个唯一的关键字。关键字的取值被用作存储数据的索引。dbm对于关键字和数据没有限制,对使用超长关键字和数据的情况也未定义任何错误。
为了操纵这些数据块,头文件ndbm.h(gdbm.h)中定义了一个名为datum的新数据类型,该类型确切的内容依赖于具体实现,它至少包含如下两个成员:
void *dptr;
size_t dsize;
datum是一个用typedef语句定义的类型,在ndbm.h文件中还为dbm声明了一个类型定义,它是一个用来访问数据库的结构,其作用和用来访问文件的FILE结构很相似。dbm类型定义的内部结构依赖于具体实现,它绝不允许直接使用。
在使用dbm库时,如果要引用一个数据块,必须声明一个datum类型的变量,将成员dptr指向数据的起点,并把成员dsize设为包含数据的长度。无论是待存储的数据或是用来访问它的索引都是通过这个datum类型来引用。
当打开一个dbm数据库时,通常会创建两个物理文件,后缀分别是.pag和.dir,并返回一个dbm指针,它被用来访问两个文件。对它们的访问只能通过dbm例程来进行。

7.3.3 dbm访问函数

主要的dbm函数的原型如下:
#include <ndbm.h>
DBM *dbm_open(const char *filename, int file_open_flags, mode_t file_mode);
int dbm_store(DBM *database_descriptor, datum key, datum content, int store_mode);
datum dbm_fetch(DBM *datebase_descriptor, datum key);
void dbm_close(DBM *database_descriptor);
1.dbm_open函数
这个函数用来打开已有的数据库,也可以用来创建新数据库,filename参数是一个基本文件名,它不包含.dir或者.pag后缀。第二个参数控制数据库的读、写和读/写权限。如果要创建一个新的数据库,这个标志必须与O_CREAT进行二进制或才允许文件被创建。第三个参数指定将被创建的文件的初始权限。
dbm_open返回一个指向DBM类型的指针,它将用于所有后续对数据库的访问,如果失败,它将返回(DBM*)0
2.dbm_store函数
dbm_store函数把数据存储到数据库,所有数据在存储时都必须有一个唯一的索引,为了定义要存储的数据和用来引用它的索引,必须设置两个datum类型的参数:一个用于引用索引,一个用于实际数据。最后一个参数store_mode用于控制当试图以一个已有的关键字来存储数据时发生的情况。如果它被设置为dbm_insert,存储操作将失败并且dbm_store返回1.如果它被设置为dbm_replace,则新数据将覆盖已有数据并且dbm_store返回0.当发生其他错误时,dbm_store将返回一个负值。
3.dbm_fetch函数
dbm_fetch函数用于从数据库中检索数据。它使用一个先前dbm_open调用返回的指针和一个指向关键字的datum类型结构作为其参数。它返回一个datum类型的结构。如果在数据库中找到与这个关键字关联的数据,返回的datum结构的dptr和dsize成员的值将被设置为相应数据的值。如果没有找到关键字,dptr将被设置为null。
4.dbm_close函数
这个函数关闭用dbm_open打开的数据库,它的参数是先前dbm_open调用返回的dbm指针。
编写dbm程序dbm1.c
首先,打开数据库,如果需要就创建它,接着,填充作为测试数据的items_to_store的3个成员。针对每个成员,分别创建一个索引关键字(使用两个字符串的头一个字符加上整数)。然后,设置两个datum结构,一个用于关键字,另一个用于存储的数据。再把3个数据项存储到数据库中之后,构建一个新的关键字并设置一个datum结构来指向它。然后,使用这个关键字从数据库中检索数据。通过检查返回的datum结构中的dptr成员是否为null,来判断检索是否成功。

7.3.4 其他dbm函数

int dbm_delete(DBM *database_descriptor, datum key);
int dbm_error(DBM *database_descriptor);
int dbm_clearerr(DBM *database_descriptor);
datum dbm_firstkey(DBM *database_descriptor);
datum dbm_nextkey(DBM *database_descriptor);
1.dbm_delete函数
用于从数据库中删除数据项,它使用一个指向关键字的datum类型结构作为其参数。
2.dbm_error函数
用于测试数据库中是否有错误发生。
3.dbm_clearerr函数
用于清除数据库中所有已被置位的错误条件标志
4.dbm_firstkey和dbm_nextkey函数
这两个函数一般成对使用对数据库中的所有关键字进行扫描。它们需要的循环结构如下所示:
DBM *db_ptr;
datum key;
for (key = dbm_firstkey(db_ptr); key.dptr; key = dbm_nextkey(db_ptr));
编写程序dbm2.c

本类排行

今日推荐

热门手游