第一篇:图书仓库管理系统的设计
图书仓库管理系统的设计(1)摘 要
本系统主要完成对图书仓库的库存管理,包括图书入库、出库、库存,员工信息,供应商信息以及密码管理等六个方面。系统可以完成对各类信息的浏览、查询、添加、删除、修改、报表等功能。
系 统的核心是入库、库存和出库三者之间的联系,每一个表的修改都将联动的影响其它的表,当完成入库或出库操作时系统会自动地完成库存的修改。查询功能也是系 统的核心之一,在系统中即有单条件查询和多条件查询,也有精确查询和模糊查询,系统不仅有静态的条件查询,也有动态生成的条件查询,其目的都是为了方便用 户使用。系统有完整的用户添加、删除和密码修改功能,并具备报表打印功能。
系统采用Microsoft Office中的Access 2000来设计数据库,并使用当前优秀的开发工具—Delphi 6.0,它有着最为灵活的数据库结构,对数据库应用有着良好的支持。
论文主要介绍了本课题的开发背景,所要完成的功能和开发的过程。重点的说明了系统设计的重点、设计思想、难点技术和解决方案。
关键字:数据库,SQL语言,Delph 6,数据库组件,仓库管理
目 录
第一章 引言 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„1
1.1 课题来源 „„„„„„„„„„„„„„„„„„„„„„„„„„1 1.2 开发工具的选择 „„„„„„„„„„„„„„„„„„„„„„„2 1.3 所做的主要工作 „„„„„„„„„„„„„„„„„„„„„„„3 第二章 数据库概论 „„„„„„„„„„„„„„„„„„„„„„„„„„4
2.1 数据库的发展 „„„„„„„„„„„„„„„„„„„„„„„„4 2.1.1 数据库的发展 „„„„„„„„„„„„„„„„„„„„„„4 2.1.2 数据库阶段的特点 „„„„„„„„„„„„„„„„„„„„5 2.1.3 数据库技术 „„„„„„„„„„„„„„„„„„„„„„„6 2.2 数据库理论基础 „„„„„„„„„„„„„„„„„„„„„„„7 2.2.1 数据库模型 „„„„„„„„„„„„„„„„„„„„„„„7 2.2.2 数据库体系结构 „„„„„„„„„„„„„„„„„„„„10
2.2.3 数据的独立性 „„„„„„„„„„„„„„„„„„„„„11 2.2.4 范式 „„„„„„„„„„„„„„„„„„„„„„„„„11 2.3 SQL语言基础 „„„„„„„„„„„„„„„„„„„„„„„13 2.3.1 SQL简介 „„„„„„„„„„„„„„„„„„„„„„„13 2.3.2 SQL查询 „„„„„„„„„„„„„„„„„„„„„„„13 2.3.3 SQL数据更新 „„„„„„„„„„„„„„„„„„„„„14 第三章数据库开发工具 „„„„„„„„„„„„„„„„„„„„„„„16 3.1 Delphi 6.0 简介 „„„„„„„„„„„„„„„„„„„„„„„16 3.2 Delphi 6.0 控件 „„„„„„„„„„„„„„„„„„„„„„„17
3.2.1 ADO数据访问组件 „„„„„„„„„„„„„„„„„„„17 3.2.2 数据控制类DataControl „„„„„„„„„„„„„„„„„18 3.2.3 数据访问类DataAccess „„„„„„„„„„„„„„„„„18 3.2.4 SQL语言在Delphi中的应用 „„„„„„„„„„„„„„„19 3.3 Access 简介 „„„„„„„„„„„„„„„„„„„„„„„„21 第四章 系统总体设计 „„„„„„„„„„„„„„„„„„„„„„„„23
4.1 系统需求分析 „„„„„„„„„„„„„„„„„„„„„„„23 4.2 系统概要设计 „„„„„„„„„„„„„„„„„„„„„„„25 4.2.1 系统结构设计 „„„„„„„„„„„„„„„„„„„„„25 4.2.2 数据库设计 „„„„„„„„„„„„„„„„„„„„„„27
4.2.2.1 ER图设计 „„„„„„„„„„„„„„„„„„„„27 4.2.2.2 数据库表格设计„„„„„„„„„„„„„„„„„„29 4.3系统详细设计„„„„„„„„„„„„„„„„„„„„„„„„34 第五章 系统应用程序设计 „„„„„„„„„„„„„„„„„„„„„„37
5.1 系统窗体模块组成„„„„„„„„„„„„„„„„„„„„„„37 5.2 数据模块窗体设置„„„„„„„„„„„„„„„„„„„„„„38 5.3 主窗体功能模块的实现„„„„„„„„„„„„„„„„„„„„39 5.4 入库、出库窗体模块的实现„„„„„„„„„„„„„„„„„„43 5.5 查询功能的实现„„„„„„„„„„„„„„„„„„„„„„„51 5.6 系统登陆窗体模块的实现„„„„„„„„„„„„„„„„„„„52 5.7 用户管理功能的实现„„„„„„„„„„„„„„„„„„„„„54 5.7.1 用户管理主窗体 „„„„„„„„„„„„„„„„„„„„54 5.7.2 密码修改窗体模块的实现 „„„„„„„„„„„„„„„„54 5.7.3 用户注册窗体模块的实现 „„„„„„„„„„„„„„„„55 5.7.4 用户注销窗体模块的实现 „„„„„„„„„„„„„„„„57 结束语 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„59 致谢 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„60 参考文献 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„„61 第一章 引 言 §1.1 课题来源
随 着社会经济的迅速发展和科学技术的全面进步,计算机事业的飞速发展,以计算机与通信技术为基础的信息系统正处于蓬勃发展的时期。随着经济文化水平的显著提 高,人们对生活质量及工作环境的要求也越来越高。书籍做为人类的精神食粮,在现代社会中越来越受到重视,大量的书籍出现在市场上,人们有了各种各样不同的 选择。与此同时,为了管理大量的图书,图书仓库也大量的出现,仓库的管理问题也就提上了日程。随着图书的大量增加,其管理难度也越来越大,如何优化仓库的 日常管理也就成为了一个大众化的课题。在计算机飞速发展的今天,将计算机这一信息处理利器应用于仓库的日常管理已是势必所然,而且这也将为仓库管 理带来前所未有的改变,它可以带来意想不到的效益,同时也会为企业的飞速发展提供无限潜力。采用计算机管理信息系统已成为仓库管理科学化和现代化的重要标 志,它给企业管理来了明显的经济效益和社会效益。主要体现在:
极大提高了仓库工作人员的工作效率,大大减少了以往入出存流程繁琐,杂乱,周期长的弊端。
基于仓库管理的全面自动化,可以减少入库管理、出库管理及库存管理中的漏洞,可以节约不少管理开支,增加企业收入。
仓库的管理的操作自动化和信息的电子化,全面提高了仓库的管理水平。
随 着我国改革开放的不断深入,经济飞速的发展,企业要想生存、发展,要想在激烈的市场竞争中立于不败之地,没有现代化的管理是万万不行的,仓库管理的全面自 动化、信息化则是其中极其重要的部分。为了加快仓库管理自动化的步伐,提高仓库的管理业务处理效率,建立仓库管理系统已变得十分心要。入库、库 存、出库还是现在企业图书仓库管理的常规基本模式,虽然,最近又出现了很多新的管理模式,如:基于零库存思想的沃尔玛特管理方式,但这些新的思想在中国大 部分企业的管理中还是难以实现的。所以如何设计好仓库管理系统,尽可能地减少仓库管理的重复性和低效性就成为当前最为重要的问题。图书仓库管理的核心是入 库、库存和出库之间的联系,如何处理好三者之间的关系是系统最为关键的部分。另外,员工信息和供应商信息管理也是仓库管理中一个必不可少的部分,它提供着 与入库和出库相关的地一些信息,使得整个系统更加完整,更加实用。
通过对仓库管理日常工作的详细调查,搜集了大量的资料,从系统结构的组织,功能的实现,技术的要求以及可行性等多方面进行考虑,认为本课题是一个适应现今图书仓库管理需求的计算机信息管理系统,具有一定的实际开发价值和使用价值。
§1.2 开发工具的选择
自Java 诞生以来,随着Internet技术的普及和应用需求的变化,以第四代语言为主的应用开发产品发生了较大的变化,它们不仅已成为人们开发应用的开发工具,而且很多产品已发展成为一种强有力的应用开发环境。这些新型的开发工具通常以一种集成软件包的形式提供给开发人员,被称为Studio(工作室)或 Suite(程序组)。例如,微软的Visual Studio 6.0,Borland公司的Delphi 6.0等数据库辅助开发工具。
现在,市场上可以选购的应用开发产品很多,流行的也有数十种。目前在我国市场上最为流行、使用最多、最为先进的可用作企业级开发工具的产品有: Microsoft公司的Visual Basic 6.0版 Microsoft公司的Visual C++6.0版 Borland公司的Delphi 6.0版
在 目前市场上这些众多的程序开发工具中,有些强调程语言的弹性与执行效率;有些则偏重于可视化程序开发工具所带来的便利性与效率的得高,各有各的优点和特 色,也满足了不同用户的需求。然而,语言的弹性和工具的便利性是密不可分的,只有便利的工具,却没有弹性的语言作支持,许多特殊化的处理动作必需要耗费数 倍的工夫来处理,使得原来所标榜的效率提高的优点失去了作用;相反,如果只强调程语言的弹性,却没有便利的工具作配合,会使一些即使非常简单的界面处理动 作,也会严重地浪费程序设计师的宝贵时间。而Delphi是一个非常理想选择。Delphi 6 是操作系统中快速应用开发环境的最新版本。它也是当前Windows平台上第一个全面支持最新Web服务的快速开发工具。无论是企业级用户,还是个人开发 者,都能够利用Delphi 6 轻松、快捷地构建新一代电子商务应用。Delphi 6 是惟一支持所有新出现的工业标准的RAD环境,包括XML(扩展标记语言)/XSL(可扩展样式语言),SOAP(简单对象存取协议)和WSDL(Web 服务器描述语言)等。Delphi 6 是可视化的快速应用程序开发语言,它提供了可视化的集成开发环境,这一环境为应用程序设计人员提供了一系列灵活而先进的工具,可以广泛地用于种类应用程序 设计。在Delphi 6 的集成开发环境中,用户可以设计程序代码、运行程序、进行程序错误的调试等,可视化的开发方法降低了应用程序开发的难度。Delphi的基础编程语言是具 有面向对象特性的Pascal语言,即Object Pascal。Object Pascal具有代码稳定、可读性好、编译速度快等优点,并将面向对象的概念移植到了Pascal语言中,使这种基础语言有了新的发展空间。使用 Delphi 6.0,我们几乎可以作任何事情,还可以撰写种各种类型的应用程序,动态链接库(DLL)、CON、或CORBA对象,CGI/ISAPI程序,Microsoft Back Office应用程序。程序的规模小到简单的个人数据库应用,大到复杂的企业的多层次分布式系统,都可以使用Delphi进行开发,其友好的集成开发界 面,可视化的双向开发模式,良好的数据库应用支持高效的程序开发和程序运行,备受广大程序开发人员的好评。尤其是Delphi对数据库应用的强大支持,大 大提高了数据库应用软件开发的效率,缩短了开发周期,深受广大数据库应用程序设计人员的喜爱。Delphi为数据库应用开发人员提供了丰富的数据库开发组 件,使数据库应用开发功能更强大,控制更灵活,编译后的程序运行速度更快。§1.3 本文所做工作
引言部分介绍了本系统的课题来源以及对数据库开发工具的选择。
第二章介绍了数据库的发展,关系数据库,数据库体系结构,并系统介绍了SQL语言,为设计和理解应用程序做了铺垫。第三章系统介绍了Delphi 6.0及其部分控件,SQL语言在Delphi 6.0中的应用,以及Access等。
第四章是本文的主体,按照软件工程的要求,从需求分析开始,经过概要设计最后到详细设计,完成对整个系统的设计。
第五章根据第四章的设计结果利用Access 2000和Delphi 6.0进行了具体的窗体和应用程序设计。
总结部分介绍了设计体会和编程体会,并指出了系统设计中的不足和改进的方向
图书仓库管理系统的设计(2)第二章 数据库概论 §2.1 数据库的发展
数据库处理在信息系统的研究中一直是非常重要的主题,然而,近年来,随着World Wide Web(www.xiexiebang.com公司的TOTAL等
(3)关系模型。关系模型的主要是用二维表格结构表达实体集,用外键表示实体间联系。关系模型是由若干个关系模式组成的集合。关系模式相当于前面提到的记录类型,它的实例称为关系,每个关系实际上是一张二维表格。
关 系模型和层次、网状模型的最大判别是用关键码而不是用指针导航数据,表格简单用户易懂,编程时并不涉及存储结构,访问技术等细节。关系模型是数学化模型。SQL语言是关系数据库的标准化语言,已得到了广泛的应用。20世纪70年代对关系数据库的研究主要集中在理论和实验系统的开发方面。80年代初才形成产 品,但很快得到广泛的应用和普及,并最终取代了层次、网状数据库产品。现在市场上典型的关系DBMS产品有DB2、ORACLE、SYBASE、INFORMIX和微机型产品Foxpro、Access等。
关系模型和网状、层次模型的最大区别是:关系模型用表格数据而不是通过指针链来表示和实现实体间联系。关系模型的数据结构简单、易懂。只需用简单的查询语句就可对数据库进行操作。
关系模型是数学化的模型,可把表格看成一个集合,因此集合论、数理逻辑等知识可引入到关系模型中来。关系模型已是一个成熟的有前途的模型,已得到广泛应用。(4)面向对象模型。目前,关系数据库的使用已相当普遍,但是,现实世界中仍然存在着许多含有复杂数据结构的应用领域,例如,CAD数据、图形数据等,而关系模 型在这方面的处理能力就显得力不从心。因此,人们需要更高级的数据库技术来表达这类信息。面向对象的概念最早出现在程序设计语言中,随后迅速渗透到计算机 领域的每一个分支。面向对象数据库是面向对象概念与数据库技术相结合的产物。
面向对象模型能完整地描述现实世界的数据结构,具有丰富的表达能力,但模型相对较复杂,涉及的知识面也广,因此面向对象数据库尚未达到关系数据库那样的普及程度。
2.2.2 数据库体系结构
数 据库的体系结构分三级:内部级(internal),概念级(conceptual)和外部级(external)。这个三级结构有时也称为“三级模式结 构”,或“数据抽象的三个级别”,最早是在1971年通过的DBTG报告中提出,后来收入在1975年的美国ANSI/SPARC报告中。虽然现在 DBMS的产品多种多样,在不同的操作系统支持下工作,但是大多数系统在总的体系结构上都具有三级模式的结构特征。从某个角度看到的数据特性称为“数据视 图”(data view)。
外部级最接近用户,是单个用户所能看到的数据特性。单个用户使用的数据视图的描述称为“外模式”。
概念级涉及到所有用户的数据定义,是全局的数据视图。全局数据视图的描述称为“概念模式”。
内部级最接近于物理存储设备,涉及到实际数据存储的结构。物理存储数据视图的描述称为“内模式”。
数据库的三级模式结构是数据的三个抽象级别。它把数据的具体组织留给DBMS去做,用户只要抽象地处理数据,而不必关心数据在计算机中的表示和存储,这样就减轻了用户使用系统的负担。
三级结构之间往往差别很大,为了实现这三个抽象级别的联系和转换,DBMS在三级结构之间提供两个层次的映象(mappings):外模式/模式映象,模式/内模式映象。此处模式是概念模式的简称。2.2.3 数据的独立性
由于数据库系统采用三级模式结构,因此系统具有数据独立性的特点。在数据库技术中,数据独立性是指应用程序和数据之间相互独立,不受影响。数据独立性分成物理数据独立性和逻辑数据独立性两级。(1)物理数据独立性
如果数据库的内模式要进行修改,即数据库的存储设备和存储方法有所变化,那么模式/内模式映象也要进行相当的修改,使概念模式尽可能保持不变。也就是对内模式的修改尽量不影响概念模式,当然,对于外模式和应用程序的影响更小,这样,我们称数据库达到了物理数据独立性。(2)逻辑数据独立性
如果数据库的概念模式要进行修改,譬如增加记录类型或增加数据项,那么外模式/模式映象也要进行相应的修改,使外模式尽可能保持不变。也就是对概念模式的修改尽量不影响外模式和应用程序,这样,我们称数据库达到了逻辑数据独立性。
现有关系系统产品均提供了较高的物理独立性,而对逻辑独立性的支持尚有欠缺,例如,对外模式的数据更新受到限制等。2.2.4 范式
建 立起一个良好的数据指标体系,是建立数据结构和数据库的最重要的一环。一个良好的数据指标体系是建立DB的必要条件,但不是充分条件。我们完全可以认为所 建指标体系中的一个指标类就是关系数据库中的一个基本表,而这个指标类下面的一个个具体指标就是这个基本表中的一个字段。但如果直接按照这种方式建库显然 还不能算最佳。对于指标体系中数据的结构在建库前还必须进行规范化的重新组织。在数据的规范化表达中,一般将一组相互关联的数据称为一个关系(relation),而在这个关系下的每个数据指标项则被称为数据元素(data element),这种关系落实到具体数据库上就是基本表,而数据元素就是基本表中的一个字段(field)。规范化表达还规定在每一个基本表中必须定义 一个数据元素为关键字(key),它可以唯一地标识出该表中其它相关的数据元素。在规范化理论中表是二维的,它有如下四个性质:
在表中的任意一列上,数据项应属于同一个属性(如图中每一列都存放着不同合同记录的同一属性数据)。
表中所有行都是不相同的,不允许有重复组项出现(如图中每一行都是一个不同的合同记录)。
在表中,行的顺序无关紧要(如图中每行存的都是合同记录,至于先放哪一个合同都没关系)。
在表中,列的顺序无关紧要,但不能重复(如图中合同号和合同名谁先谁后都没关系,但二者不可重复或同名)。
在 对表的形式进行了规范化定义后,数据结构还有五种规范化定义,定名为规范化模式,称为范式。在这五种范式中,一般只用前三种,对于常用系统就足够了。而且 这五种范式是“向上兼容”的,即满足第五范式的数据结构自动满足一、二、三、四范式,满足第四范式的数据结构自动满足第一、二、三范式,„„,依此类推。
第 一范式(first normal form,简称1st NF)就是指在同一表中没有重复项出现,如果有则应将重复项去掉。这个去掉重复项的过程就称之为规范化处理。在本文所讨论的开发方法里,1st NF实际上是没有什么意义的。因为我们按规范化建立的指标体系和表的过程都自动保证了所有表都满足1st NF。
第二范式(second normal form,简称 2nd NF)是指每个表必须有一个(而且仅一个)数据元素为主关键字(primary key),其它数据元素与主关键字一一对应。例如,在图l9.7中如果我们将合同号定义为主关键字(其它数据元素中的记录数据都有可能重名,故不能作为主 关键字),故只要知道了一个合同记录的合同号,就可以唯一地在同一行中找到该合同的任何一项具体信息。通常我们称这种关系为函数依赖(functional depEndence)关系。即表中其它数据元素都依赖于主关键字,或称该数据元素唯一地被主关键字所标识。
第三范式(third normal form,简称 3rd NF)就是指表中的所有数据元素不但要能够唯一地被主关键字所标识,而且它们之间还必须相互独立,不存在其它的函数关系。也就是说对于一个满足了 2nd NF的数据结构来说,表中有可能存在某些数据元素依赖于其它非关键宇数据元素的现象,必须加以消除。
为防止数据库出现更新异常、插入异常、删除异常、数据冗余太大等现象,关系型数据库要尽量按关系规范化要求进行数据库设计。
§2.3 SQL语言基础 2.3.1 SQL简介
用户对数据库的使用,是通过数据库管理系统提供的语言来实现的。不同的数据库管理系统提供不同的数据库语言。关系数据库管理系统几乎都提供关系数据库标准语言——SQL。
SQL 的全称是Structured Query Language,即结构化查询语言。SQL语句可以从关系数据库中获得数据,也可以建立数据库、增加数据、修改数据。1986年ANSI采用SQL语言 作为关系数据库系统的标准语言,后被国际化标准组织(ISO)采纳为国际标准。SQL语言使用方便、功能丰富、简洁易学,是操作数据库的工业标准语言,得 到广泛地应用。例如关系数据库产品DB2、ORACLE等都实现了SQL语言。同时,其它数据库产品厂家也纷纷推出各自的支持SQL的软件或者与SQL的 接口软件。这样SQL语言很快被整个计算机界认可。SQL语言是一种非过程化语言,它一次处理一个记录集合,对数据提供自动导航。SQL语言允许 用户在高层的数据结构上工作,而不对单个记录进行操作。SQL语言不要求用户指定数据的存取方法,而是使用查询优化器,由系统决定对指定数据存取的最快速 手段。当设计者在关系表上定义了索引时,系统会自动利用索引进行快速检索,用户不需知道表上是否有索引或者有什么类型的索引等细节。
SQL语言可以完成许多功能,例如: ● 查询数据
● 在数据库表格中插入、修改和删除记录 ● 建立、修改和删除数据对象 ● 控制对数据和数据对象的存取 ● 确保数据库的一致性和完整性等 2.3.2 SQL查询
数据查询是关系运算理论在SQL语言中的主要体现,SELECT 语句是SQL查询的基本语句,当我们在对一个数据库进各种各样的操作时,使用的最多的就是数据查询,在以SQL为基础的关系数据库中,使用的最多的就是SELECT查询语句。SELECT语句的完整句法如下:
SELECT 目标表的列名或列表达式序列 FROM 基本表和(或)视图序列 [WHERE 行条件表达式] [GROUP BY 列名序列] [HAVING 组条件表达式] [ORDER BY列名 [ASC│DEAC]„]
我 在SELECT语句中还使用了大量的保留字和通配符以进行各种各样的条件查询。在系统中有大量的查询按钮,其使用了大量的查询语句,而且这些查询语句大部 分使用的是模糊查询,所以大量的使用了模式匹配符LIKE(判断值是否与指定的字符通配格式相符)。在包含LIKE的查询语句中可以使用两个通配符:%(百分号):与零个或多个字符组成的字符串匹配;_(下划线):与单个字符匹配。系统中的条件判断往往包含多个条件,这时就需要使用逻辑运算符NOT、AND、OR(用于多条件的逻辑连接),谓词ALL以及保留字DISTINCT等等。做为SELECT语句还有很多的使用方法,这里就不再叙述。2.3.3 SQL数据更新
使用数据库的目的是为了有效地管理数据,而数据的插入、删除和修改则是必不可少的一个功能。在本系统中就大量地使用了数据插入、删除和修改这三种操作,现做一个简单地介绍。●数据插入
往数据库的基本表中插入数据使用的是INSERT语句,其方式有两种:一种是元组值的插入,另一种是查询结果的插入。在本系统中使用的是前一种方式,其句法如下:
INSERT INTO 基本表名(列表名)VALUES(元组值)●数据删除
往数据库的基本表中删除数据使用的是DELETE语句,其句法如下: DELETE FROM 基本表名 [WHERE 条件表达式] 在 些作一点说明,删除语句实际上是“SELECT * FROM 基本表名 [WHERE 条件表达式]”和DELETE操作的结合,每找到一个元组,就把它删除。此外,DELETE语句只能从一个基本表中删除元组,WHERE子句中条件可以嵌 套,也可以是来自几个基本表的复合条件。●数据修改
当需要修改基本表中元组的某些列值时,可以用UPDATE语句实现,其句法如下: UPDATE基本表名
SET列名=值表达式[,列名=值表达式„] [WHERE条件表达式] 在Delphi 中使用SQL语句是很方便的,一般来说,都是通过TQuery组件来使用SQL语言的。有一点要进行说明,虽然通过TQuery组件来使用SQL语言很方 便,但考虑到自己对不同组件的理解程度、个人习惯以及其它各个方面,在本系统中我采用的是ADO组件来对数据库进行操作。最简单的方法比如在 TADOQuery组件的SQL属性中就可以键入SQL语句,至于详细的使用方法在后面进行介绍。
图书仓库管理系统的设计(3)第三章 数据库开发工具 §3.1 Delphi 6.0 简介
Delphi类可以粗略地分成两部分:一部分是组件 类,这些组件类通常以某种方式出现在组件面板上,当用户从组件面板上点取一个类的图标后,在程序中就自动生成了该类的对象(非可视组件除外);另一部分是 功能类,这此功能类的对象通常出现在程序代码中,起着不可代替的作用,但是这些功能类在组件面板上是找不到的。在Delphi中,每一个类的祖先都是 Tobject类,整个类的层次结构就像一棵倒挂的树,在最顶层的树根即为Tobject类。这样,按照面向对象编程的基本思想,就使得用户可用 Tobject类这个类型代替任何其它类的数据类型。实际上在Delphi的类库中,Tobject类派生出了为数相当众多的子类,它们形成了一个庞大的 体系,通常情况下,如果不自行开发组件,就不必了解整个类的体系结构,只用到类层次树的叶结点就足够了。
凡是做过程序开发的人都知道从来没有单纯 的数据应用程序,也就是说,数据库应用程序必须和用户界面(可以是图形界面,也可以是命令接口)元素相结合,只讲界面或只讲数据库本身都构不成数据库应用 程序,因而用Delphi 6.0开发数据库应用程序就隐含着界面开发。Delphi6中的VCL组件可用图3-1来说明。组件在Delphi程序的开发中是最显眼的角色。大家知 道,在编写程序时一般都开始于在组件面板上选择组件并定义组件间的相互作用。但也有一些组件不在组件面板上,例如Tform和Tapplication(典型的非可视组件)。组件是Tcomponents派生出来的子类,可以流的形式存放在DFM文件中,具有事件和Publish属性。
窗口组件类是窗口化的可视化组件类,在Delphi的类库中占有最大的份额。在实际编程中,窗口组件类的对象都有句柄,可以接受输入焦点和包含其它组件。图 形组件与窗口组件并列,是另一大类组件。图形组件不是基于窗口的,因而不能有窗口句柄,不能接受输入焦点和包含其它组件。从图8-43中可以看出,图形组 件的基类是TgraphicControl,在实际编程中,它们必须寄生于它们的宿主——窗口组件类的对象,由它们的拥有者负责其显示,而且它们还能触发 一些和鼠标活动相关的事件。图形控件最典型的例子是Tlabel和TspeedButton。由此可以看出图形组件的功能很弱,有读者会问图形组件的用处 何在呢?其实使用图形组件的最大好处在于节省资源,正是因为它们的功能较弱,所以使用的系统资源就要少。在一个应用程序中,如果能在不影响其功能的前提下 合理大量地使用图形组件,将会大减少程序对系统资源的消耗。非可视组件是与可视组件相并列的另一类组件,非可视组件在程序运行中是不可见的(除各种对话框组件之外,事实上有人认为对话框组件不能归入非可视组件,应该是另一种介于可视与非可视之间的组件)。§3.2 Delphi 6.0 控件
用Delphi6开发数据库应用,重点是和各种数据库组件打交道,当然也要使用其它的一些组件,现在就我在系统设计中所使用的重要组件给与简单介绍。3.2.1 ADO数据访问组件
ADO 数据对象(Active Data Objects)实际是一种提供访问各种数据类型的链接机制。ADO设计为一种极简单的格式,通过ODBC的方法同数据库接口中,可以使用任何一种 ODBC数据源,即不止适合于SQL Server、Oracle、Access等数据库应用程序,也适合于Excel表格、文本文件、图形文件和无格式的数据文件。ADO是基于OLE-DB 之上的技术,因此ADO通过其内部的属性和方法提供统一的数据访问接口方法。ADO使您的客户端应用程序能够通过OLE DB提供访问和操作在数据库服务器中的数据。ADO支持用于建立C/S和Web的应用程序的主要功能。其主要优点是易于使用、高速度、低内存支出和占用磁 盘空间较少。ADO同时具有远程数据服务(RDS)功能,通过RDS可以在一次往返过程中实现将数据从服务器移动到客户端应用程序和Web页、在客户端对 数据进行处然后将更新结果返回服务器的操作。
Delphi 6.0继续对Microsoft的ADO访问能力的支持。这种能力是通过一组新组件实现的,这些组件是在企业版的ADO组件页中,在组件面版的ADO页上 可以找到这些组件。利用在前面章节提到的TdataSet抽象类,ADO组件可以不通过BDE而直接实现ADO连接。这意味着只需要很少的代码就可以实现 该连接并且性能得到提高。
利用ADO数据访问组件,可以只使用ADO结构与数据库取得联系并对其中的数据进行操作,而在这些过程中完全不需要使用 BDE。大多数的ADO连接和数据集组件都是与基于BDE的连接和数据集组件相类似的。TADOConnection组件与基于BDE的应用程序中的 Tdatabase组件类似。TADOTable与Ttable,TADOQuery与Tquery,以及TADOStoreProc和 TstoredProc之间都具有这种类似的对应关系。使用这些ADO组件的方式与我们常使用的数据访问组件(基于BDE)都有许多相同之处。TTADODataSet没有直接的BDE对应组件,但它提供了许多与Ttable和Tquery相同的功能。同样,TADOCommand也没有相对应 的BDE组件,它是在Delphi/ADO环境中完成特定功能的组件。Delphi 6.0通过ADO数据集访问组件,可以不借助BDE数据引擎而是通过微软的OLEDB来访问更为广泛的数据库中的数据。ADO数据集访问组件与常用的数据 访问组件是并列的关系。在系统中我主要使用的是ADOTablet和ADOQuery两个组件。3.2.2 数据控制类DataControl 数 据控制类负责数据库数据的显示,并把用户对数据的修改传回。这里的绝大多数组件,如DBText, DBEdit, DBMemo, DBImage, DBListBox, DBComboBox, DBCheckBox, DBRadioGroup, DBLookupListBox, DBLookupCombox, DBCtrGrid的功能和对应的非数据感知组件相同,如TEdit框,TRadioGroups单选按钮组等,只不过在显示数据库数据时要用而已。
在系统中主要使用数据网格控件DBGrid和数据库导航器控件DBNavigator。3.2.3 数据访问类DataAccess 数 据库应用系统中数据访问是一个首要问题,包括单用户和 C/S系统,都必须联系一些数据库和数据表文件。Delphi 6 提供了专门用于数据访问的基类控件。主要包括数据源控件DataSource、客户数据集控件ClientDataSet、数据集提供器控件 DataSetProvider等等。
Tdatabase:当一个基于BDE的数据库应用程序需要一个永久数据库连接时,需要定制向一个数据库服 务器的连接时,需要事务控制和特殊的数据库别名时就得用到Tdatabase对象。特别是当连接到一个远程的SQL数据库服务器时,如果要利用BDE进行 数据库事务处理,那么,TDatabase对象的威力就体现出来了。在一个应用程序中为每一个数据库连接显示的声明Tdatabase对象要根据需要而 定,不是必需的。对一个数据库连接,如果没有显示的声明并实例化TDatabase对象,系统就会产生一个带有默认属性的TDatabase对象。
TdataSource 对象用于在DataSet对象(包括Tquery,TstoredProc,Ttable等)和数据感知组件之间提供一个连接的纽带,以便在窗体上显示数 据库中的数据,在数据库中导航定位与编辑数据集中的数据。如果一个DataSet对象中的数据想在数据感知组件中显示和修改,它就必须和 TdataSource对象相联系。同样,一个数据感知组件如果想和数据源相联系以便显示和操纵数据,就必须以TDataSource对象为中介。
用Delphi6作数据库应用开发概括来说如下:先利用数据存取组件和实际的数据库建立连接,并用Tsession对象和Tdatabase对象管理这些连接。然后以Tdatasource对象为中介,用数据感知组件向用户显示数据库的内容并接受用户的查询和修改等操作。
3.2.4 SQL语言在Delphi中的应用
在Delphi 中使用SQL语言非常方便,一般来说,都是通过Tquery组件来使用SQL语言的。可以在TQuery组件的SQL属性中设置SQL语句。设计程序时,在该组件的属性对话框中选择SQL属性,单击带省略号的按钮,就可以打开String List Editor对话框,然后我们就可以在对话框中添加SQL语句。还可以使用Delphi的SQL Builder来自动生成SQL语句,这样可以避免手工编写SQL而可能造成的语法错误。
静态SQL语句在程序设计时便已固定下来,它不包含任何参数和变量。
动态SQL语句,也被称作参数化的语句,在其中间包含着表示字段名或表名的参数,例如下面的语句是一条动态SQL语句:
Select * From Students Where StudentCode =: StudentCode;其中的变量StudentCode便是一个参数变量,它由一个冒号引导,在程序运行过程中,必须要为该参数赋值,该条SQL语句才能正确执行,每次运行应用程序时可以为该参数变量赋予不同的值。为参数赋值有三种方法: ①根据参数在SQL语句中出现的顺序,设置TQuery部件的Params属性值为参数赋值。
②直接根据SQL语句中各参数的名字,调用ParamByName方法来为各参数赋值。③将TQuery部件的DataSource属性设置为另一个数据源,这样将另一个数据源中与当前TQuery部件的SQL语句中的参数名相匹配的字段值赋给其对应的参数。利用这种方法也能实现所谓的连接查询,创建主要—明细型数据库应用。
在程序运行过程中,要想设置TQuery部件的SQL属性,必须首先调用Close方法,关闭TQuery部件,然后再调用Clear方法清除SQL属性中现存的SQL命令语句,最后再调用Add方法为SQL属性设置新的SQL命令语句。例如: Query1.Close {关闭Query1)Query1.SQL.Clear {清除SQL属性中的SQL命令语句} Query1.SQL.Add(‘Select * From Students‘);Query1.SQL.Add(‘ Where Name =“Lucy” ‘);
在 为TQuery部件设置SQL属性时调用Close方法总是很安全的,如果TQuery部件已经被关闭了,调用Close方法时不会产生任何影响。在应用 程序中为SQL属性设置新的SQL 命令语句时,必须要调用Clear方法以清除SQL属性中现存的SQL命令语句,如果不调用Clear方法,便调用Add方法向SQL属性中设置SQL命 令语句,那么新设置的SQL命令语句会追加在现存SQL命令语句后面,在程序运行时常常会出现出乎意料的查询结果甚至程序无法运行下去。在这里 要特别注意的,一般情况下TQuery部件的SQL属性只能包含一条完整的SQL语句,它不允许被设置成多条SQL语句。当然有些数据库服务器也支持在 TQuery部件的SQL属性中设置多条SQL语句,只要数据库服务器允许这样,我们在编程时可以为 SQL 属性设置多条SQL语句。
在为TQuery部件设置完SQL属性的属性值之后,也即编写好适当的SQL程序之后,可以有多种方式来执行SQL程序。
在 设计过程中,设置完TQuery部件的SQL属性之后将其Active属性的值置为True,这样便可以执行SQL属性中的SQL程序,如果应用中有与TQuery部件相连的数据浏览部件(如TDDGrid TDBEdit等)那么在这些数据浏览部件中会显示SQL程序的执行结果。
在应用程序运行过程中,通过程序调用TQuery部件的Open方法或 ExecSQL 方法可以执行其SQL属性中的SQL程序。Open方法和ExecSQL方法是不一样的。Open方法只能用来执行SQL语言的查询语句(Select命 令),并返回一个查询结果集,而ExecSQL方法还可以用来执行其它常用的SQL语句(如INSERT, UPDATE, DELETE等命令),例如:
Query1.Open(这样会返回一个查询结果集)如果调用Open方法,而没有查询结果时,会出错。此时应该调用ExecSQL 方法来代替Open方法。如:
Query1.ExecSQL(没有返回结果)当 然在设计应用程序时,程序设计人员是无法确定TQuery部件中的SQL 语句是否会返回一个查询结果的。对于这种情况应当用Try„Except模块来设计程序。在 Try 部分调用Open方法,而在Except部分调用ExceSQL方法,这样才能保证程序的正确运行。
Delphi中用ADOQuery来使用 SQL语句同样十分方便。在ADOQuery组件中首先通过ConnectionString属性值来联接数据源,然后就通过双击SQL„属性值来写入 SQL语句。在Delphi中调用数据库,就可以调用ADOQuery组件,通过修改其中的SQL„属性中的SQL语句来实现对数据库的各项操作。
值 得注意的是,ADOQuery组件只有在激活的情况下才可以被正确地使用,这样就提出了一个问题,也就是说,在每次修改ADOQuery组件的SQL„属 性时都必须先行进行关闭,待清除掉SQL„中所有的SQL语句后才可以添加新的SQL语句。而且,在每一次修改完成以后,还应该记得重新将 ADOQuery激活。其它的使用方法与TTQuery有许多的相似之处。§3.3 Access 简介
建立一个数据库我们有多种选择,现在市场上有各种各样的数据库,而且每一种数据库都有其自身的特点,不能说哪一种更好,只能在其中寻找一种能更好地适应系统需求、更好地满足用户的要求以 及适应开发人员的习惯。在本系统中,做为图书仓库管理系统是一个比较小的应用系统,它所产生和处理的数据量也比较小。因此,没有必要使用像SQL Server和Oracle这样的大型数据库。我首先想到的数据库是Borland公司的Paradox数据库。另外,Microsoft Office中的Access数据库在计算机上的应用比较普及,是开发小型数据库系统的比较理想的选择,所以,在本系统中我选择了Access数据库。
Access 做为一个数据库管理系统,它被集成在Microsoft Office中。Access数据库处理的基本结构,采取关系型数据库模式。与其他的数据库系统相比,Access更加简单易学,一个普通的计算机用户可 以很快地掌握它。Access 2000的功能十分强大,利用它可以方便地实现对信息保存、维护、查询、统计、打印、交流、发布,而且它可以十分方便地与Office其他组件交流数据,这些功能对一个一般用户而言已经足够了。
图书仓库管理系统的设计(4)第四章 系统总体设计
软件系统的总体设计大约要经历可行性分析和项目开发计划,需求分析,概要设计,详细设计,编码,测试以及 维护等七个阶段。可行性分析和项目开发计划在前面已经叙述,下面所要做的是进行软件需求分析,概要设计和详细设计。编码过程将在下一节论述,而测试和维护 过程不在本文叙及。§4.1 系统需求分析
在经过前一阶段的分析之后,我确定了我的开发课题为图书仓库管理。现在所要做的是要准确定义系统必须做什么以及系统必须具备的功能。
软 件需求分析中我采用结构化分析方法(Structured Analysis,简称SA),SA是面向数据流进行需求分析的方法,像所有的软件分析方法(如面向对象分析方法、IDEF方法等等)一样,SA也是一种 建模活动,它使用简单易读的符号,根据软件内部数据传递、变换的关系,自顶向下逐层分解,描绘满足功能要求的软件模型。
在系统中我采用数据流图(DFD)这种半形式化的描述方式表达需求。它是一种功能模型,以图形的方式描绘数据在系统中流动和处理的过程,只反映系统必须完成的逻辑功能。它有四种基本图形符号: ◆ →:箭头,表示数据流; ◆ 〇:圆或椭圆,表示加工; ◆ ═:双杠,表示数据存储;
◆ □:方框,表示数据的源点或终点。
为了表达较为复杂问题的数据处理过程,用一张数据流图是不够的,要按照问题的层次结构进行逐步分解,并以一套分层的数据流图反映这种结构关系。在这里我一共使用了三层数据流图,即顶层图,0层图和1层图(也是底层图)。在多层数据流图中,顶层流图仅包含一个加工,它代表被开发系统,它的输入流是该系统的输入数据了,输出流是该系统的输出数据;底层流图是指其加工不需要再做分解的数据流图,中间层流图表示对其上层父图的细化,它的每一步加工可能继续细化成子图。
经过对系统的分析首先得到系统的顶层DFD,如下: 一步细化得到系统的0层DFD,如下:
再进一步细化每一个数据加工功能,得到系统的1层DFD图。
在这里只给出有关入库管理和出库管理的1层数据流图,它们是系统的关鍵部分,也是主要的部分。通过以上对数据流图的分析之后,我们已大体地了解了系统的功能和目标,接下来所要做的就是系统功能模块的划分和数据库的设计,也就是系统的概要设计。§4.2 系统概要设计
在软件需求分析阶段,搞清楚了软件“做什么”的问题,形成了目标系统的逻辑模型。现在我们所要做的就是要把软件“做什么”的逻辑模型变换为“怎么做”的物理模型,即着手实现软件的需求。首先,我们需要描述的是系统的总的体系结构。
4.2.1 系统结构设计
系统的概要设计中最重要的就是系统的模块化。模块化是指解决一个复杂问题时自项向下逐层把软件系统划分成若干个模块的过程。每个模块完成一个特定的功能,所有的模块按某种方法组织起来,成为一个整体,完成整个系统所要求的功能。
将系统划分为多个模块是为了降低软件系统的复杂性,提高可读性、可维护性,但模块的划分不能是任意的,应尽量保持其独立性。也就是说,每个模块只完成系统 要求的独立的子功能,并且与其他模块的联系最少且接口简单,即尽量做到高内聚低耦合,提高模块的独立性,为设计高质量的软件结构奠定基础。在系统 的概要设计中我采用结构化设计(Structure Design,简称SD),SD以需求分析阶段产生的数据流图DFD为基础,按一定的步骤映射成软件结构。我首先将整个系统化分为几个小问题,小模块,在 系统中,我设计了用户管理、库存管理、入库管理、出库管理、员工管理和供应商管理6个小模块。然后,进一步细分模块,添加细节。比如,用户管理我又将其分 为用户注册、用户注销、密码修改;库存管理分为库存记录查询、库存记录修改、库存记录打印等等。以下就是系统的结构图:(在这里为了表达方便我将结构图分开来表达。)
在得到系统的第一层功能模块图后,经过进一步地细化,得一系统的子功能模块图:
4.2.2 数据库设计
在信息世界中,信息从客观事物出发流经数据库,通过决策机构最后又回到客观世界,信息的这一循环经历了三个领域: 信息世界,数据世界,现实世界。现实世界的事物反映到人的头脑中,人的大脑对它有个认识过程,经过分析(选择、命名、分类等)进入信息世界。这些信息再进 一步加工、编码,然后进数据世界,而软件系统的开发工作需要考虑这两个方面的问题,也就是要考虑系统开发所需要的数据,以及如何对这些数据进行操作。这两 个问题贯穿了整个软件系统的开发过程,这也就是数据库的设计问题,软件设计的一个核心。4.2.2.1 ER图设计
在系统设计的开始,我首先考虑的是如何用数据模型来数据库的结构与语义,以对现实世界进行抽象。目前广泛使用的数据模型可分为两种类型,一种是独立于计算机系统的“概念数据 模型”,如“实体联系模型”;另一种是直接面向数据库逻辑结构的“结构数据模型”。在本系统中我采用“实体联系模型”(ER模型)来描述数据库的结构与语 义,以对现实世界进行第一次抽象。ER模型直接从现实世界抽象出实体类型及实体间联系,然后用ER图来表示数据模型。它有两个明显的优点:接近于人的思 维,容易理解;与计算机无关,用户容易接受。但ER模型只能说明实体间语义的联系,不能进一步说明详细的数据结构,它只是数据库设计的第一步。
ER图是直观表示概念模型的工具,它有四个基本成分: ◆ 矩形框,表示实体类型(考虑问题的对象)。◆ 菱形框,表示联系类型(实体间的联系)。
◆ 椭圆形框,表示实体类型和联系类型的属性。对于关键码的属性,在属性名下划一横线。
◆直线,联系类型与其涉及的实体类型之间以直线连接。
本系统为图书仓库管理,主要管理图书的入库、出库以及库存等事项。仓库根据需要可以查询图书供应商的信息,同时还需要了解在入库和出库中员工的参与情况。依据仓库管理的实际情况,考虑了多方面的因素以后,确定系统的ER图如下:
(为了表达的方便,在这里我没有在一张图上表达出所有的关系,而是用一张总体ER图,和几张实体属性关系图来表达数据库的结构。)
在 该数据库中,我设计了三个实体,分别是库存、员工和供应商以及两个联系类型入库和出库。在本系统中库存是核心,也是基本,没有了库存其它的也就没有什么意 义了。员工记录的添加是考虑到责任问题,也就是说,在仓库管理的实际运用中,出现了责任不清的现象,特别是由于仓库的进出图书数量都比较大时产生了一系列 问题,所以在设计数据库时,我特别考虑到这一点,加入了员工记录这一实体。供应商信息的添加主要出于对图书来源问题的思考。通过添加供应商信息可以比较清 楚地了解图书的进货渠道,从图书的质量到供应商的信誉都可以进行了解,同时可以为以后的图书进购提供一定有用的信息。
入库联系类型将库存信息、供应商信息和员工信息联系在一起,可以方便地实现三个实体之间的联接,而出库联系类型则将库存信息和员工信息较好地联接起,同时这两个联系类型又都具有各自特有的属性。下面就是各实体及联系类型的属性图:(带#号的属性为关键字段)4.2.2.2 数据库表格设计
在完成系统的ER图之后,需要将ER模型转化为关系模型,也就是说,要设计出数据库所需要的表格。在这里,我选用的是关系数据库。因为关系数据库中的二维表格可以很清楚地描述数据之间的联系。
在这里不得不提到一个概念——范式。其实在上一节的ER图设计中,已经运用了范式的思想,不仅如此,在数据库的表格设计中更离不开范式的思想,它是数据库设计的基础,如果不注意这个问题将会导致一系列问题的出现。
我 在系统中定义的表格都严格地按照范式的思想和要求去完成,数据库中的所有表格都达到了三范式的要求。根据系统ER图,针对本系统的特点,在对所搜集的数据 进行规范化之后,定义了如下六张表格,分别是库存信息表,入库信息表,出库信息表,员工信息表,供应商信息表和密码信息表。通过对这六张表格的操作可以较 好地完成系统设计的各项功能,六张表格之间有着不同程度的联系。(说明:在以下数据表中,K代表主键,#代表外键,字段值不为空。)BookRecord 表(库存信息表)
字段名称 数据类型 说明 K BookID 数字 图书编号 BookName 文本 图书名 Author 文本 作者
Publisher 文本 出版社
PubDate 日期/时间 出版日期 Price 货币 价格
BookType 文本 图书类型 Number1 数字 库存数量 Addation 文本 备注 图4.13 库存信息表
库存信息表主要用于记录仓库中现存放的所有图书的详细信息,包括图书编号、书名、作者、出版社、图书类型等有关图书的各类信息,它即是该数据库的主表,也是系统主界面的主要内容。
在 该表中图书编号是主键,它按图书入库的先后次序来编写,每当有图书入库,系统自动给出图书编号,这样我们按图书编号来查找图书是比较方便的。考虑到编号比 较难于记忆,所以使用了出版社和图书类型两个字段,在系统中我提供了出版社和图书类型的分类查找,而且全部采用自动生成,每当系统中有新的出版社类型和图 书类型,弹出菜单会自动添中新类型,这样就可以比较方便地实现按出版社和按图书类型查找。此外,库存数量也是一个比较关键的字段,该字段是在系统初始化时 就给定的,每当有图书入库或出库操作,系统就会自动修改图书的库存数量,以保持数据的一致性。做为备注有一点说明,我的数据库中备注的数据类型是文本,而 不是备注类型,主要考虑到该字段的长度并不大,而且在Delphi中文本数据类型的处理也比较方便一点。Employee 表(员工信息表)字段名称 数据类型 说明 K EmployeeID 数字 员工编号 EmployeeName 文本 员工姓名 Sex 文本 性别
BornDate 日期/时间 出生日期 Grade 文本 职称
WorkDate 日期/时间 工作日期 Telephone 文本 联系电话 Address 文本 联系地址
图4.14 员工信息表
员 工信息表主要用于记录有关员工的各类信息,包括姓名、职称、出生日期、联系电话、联系地址等。它主要用来为系统提供员工的有关信息,因为在系统中,入库和 出库操作均与员工有着一定的联系,在查询入库信息和出库信息时,有时需要查找有关此项记录有关的员工信息,在系统中我是通过入库记录与员工记录(出库记录 和员工记录)之间的联接查询来完成的。另外,作为一个仓库也有必要了解其所属员工的一些基本情况,以便查询。Shopkeeper 表(供应商信息表)
字段名称 数据类型 说明
K ShopkeeperID 数字 供应商编号 ShopkeeperName 文本 供应商姓名 Address 文本 地址 PostNo 数字 邮编
OfficePhone 文本 办公电话 HomePhone 文本 住宅电话 Email 文本 E-mail PayType 文本 付款方式
图4.15 供应商信息表
供 应商信息表主要用于记录有关供应商的各类信息,包括姓名、地址、电话、付款方式等。它主要用来为系统提供供应商的有关信息,在系统中入库记录是与供应商记 录相联系的,通过入库记录可以查找相关的供应商信息。在供应商信息中,考虑当实际情况,我特别加入了Email和付款方式这两个字段,因为在当今信息世界 中,多种多样的通讯方式和多种多样的付款方式是必然的,是数据库中必须与以记录。
InRecord 表(入库信息表)
字段名称 数据类型 说明 K InID 数字 入库编号 # BookID 数字 图书编号
# EmployeeID 数字 员工编号
# ShopkeeperID 数字 供应商编号 Number 数字 入库数量
BuyDate 日期/时间 入库日期
图4.16 入库信息表 OutRecord 表(出库信息表)
字段名称 数据类型 说明 K OutID 数字 出库编号 # BookID 数字 图书编号
# EmployeeID 数字 员工编号 Number2 数字 出库数量
OutDate 日期/时间 出库日期
图4.17 出库信息表
入 库信息表主要用于记录有关入库的详细信息,包括入库数量、入库日期以及图书、员工、供应商三方的编号,以便查询。出库信息表主要用于记录有关出库的详细信 息,包括出库数量、出库日期以及图书、员工的编号。出库信息表和入库信息表一样,其实它们都属于联系类型,系统通过这两个表可以联接上其它的表为用户提供 多种条件的联接查询。值得提出的一点是入库记录和出库记录的添加不仅仅是单表操作,由于它们都与库存记录相联系,所以,无论您是添中入库记录还是添加出库 记录,都必须同时修改库存记录,以保持数据的一致性,否则将引发系统出错而这些我都让其在系统中自动完成。无论您是添加入库记录,还是添加出库记录,系统 都将自动修改库存中图书的数量,而且,在您出库的数量大于库存数量时,系统还会自动提示错误,这样就可以防止一定错误的发生。
在入库信息表和出库 信息表中我还定义了几个外键,它提供了一种表示几个关系联系的方法。比如,系统中通过在入库信息表中定义的外键 BookID、EmployeeID和ShopkeeperID可以将库存信息表、员工信息表和供应商信息表联系在一起,从而方便地实现联接查询,而且,引入外键的定义是实体完整性约束的一个主要方面。Key 表(密码信息表)
字段名称 数据类型 说明 K KeyName 文本 用户姓名 KeyNo 文本 用户密码 图4.18 密码信息表
密码信息表主要用于记录所有的用户名和用户密码。它是在用户登陆时用来确定用户和密码的正确性,以防止非法用户登陆。
通过以上设计已经完成了系统的概要设计,当我们有了系统的功能模块图和数据库之后,就需要着手去实现每一个模块,为每一个功能设计程序流程图,这也就是系统的详细设计。§4.3 系统详细设计
在前面的概要设计中,已将系统划分为多个模块,并将它们按照一定的原则组装起来,同时确定了每个功能及模块之间的外部接口。现在所要做的就是确定每个模块具体执行过程,也可以说是“过程设计”。
在 处理过程设计时我采用的是结构化程序设计(简称SP)方法。需要指出的是系统的详细设计并不是指具体的编程序,而是将概要设计阶段产生的系统功能模块图细 化成很容易产生程序的图纸。因此详细设计的结果基本决定了最终程序的质量。为软件的质量,延长软件的生存期,软件的可测试性、可维护性提供重要的保障。详 细设计的目标不仅是逻辑上正确地实现每个模块的功能,还应使设计出的处理过程清晰易读。
由前一阶段产生的系统功能模块图,我为系统的主要部分设计 了如下程序流程图:通过以上步骤,基本上完成了对整个系统的总体设计,接下来所要做的就是软件的编码工作。系统总体设计的好坏直接影响着下一步工作,只有 在这一阶段设计出好的模块图和程序流程图,才能更有利于编码,产生好的软件系统。
图书仓库管理系统的设计(5)第五章 系统应用程序设计
§5.1 系统窗体模块组成 §5.2 数据模块窗体的设置
在编写数据库应用程 序时,经常要遇到这样的情况,即好多组件、窗体同时访问相同的数据源,如果为每一个组件或者窗体都设置一个数据源将是十分耗时的工件,而且要保证这些数据 源的确是相同的也需花一番功夫。那么,能不能将这些数据源集中管理,最好是做成一个统一的模块,需要时就将该模块引入而不必直接操作数据源本身呢?数据模 块(DataModule)是解决这个问题最好的答案。简单说来,数据模块是用来集中管理数据源的一个窗体,该窗体可被需要的地方随时引入。
图5.2 给出了本程序的数据模块(datamoduleform)窗体图,除报表窗体外所有的数据存取组件和数据源组件都在此数据模块中进行了定义。值得一提的 是,设置了数据库Database组件,该组件引入了系统所需的唯一的数据库tsxs,Database组件的DatabaseName属性设置为 tsckgl。tsxs数据库已在ODBC配置程序中进行了设置。其他的数据存取组件都是基于此数据库组件创建的,这样做的好处是,当数据库的别名或者其 他信息改变之后,只需修改Tdatabase组件的AliasName属性即可。
另外,在本系统的数据模块窗体图中,我大多采用的 AODQuery组件而没有采用BDE组,这主要是基于对ADO组件的了解。在Delphi的学习中我对ADO组件了解的更加清楚,使用也较BDE更为熟 练,而且,ADO组件的功能也较BDE更为强大,所以在这里大多采用ADO组件来进行数据库联接。同时我也使用了BDE组件中的Table,因为在某些时 候BDE有着其自身特有的优越性。主窗体功能模块的实现 file://主窗体程序代码
public file://在程序的起始部分,定义快捷按钮点击事件 Procedure Popup1Handler(Sender:Tobject);Procedure Popup2Handler(Sender:TObject);********************************************************************** procedure Tmainform.Popup1Handler(Sender: TObject);begin file://快捷按钮1(点“按出版社分类”按钮产生)的点击事件 with datamoduleform.MainQuery do begin file://打开数据模块窗体的MainQuery,对BookRecord表进行操作 close;file://关闭MainQuery SQL.Clear;file://清除SQL属性中的SQL命令语句 SQL.Add(‘select * from BookRecord where Publisher=:Pub‘);file://添加新的SQL语句
Parameters.ParamByName(‘Pub‘).Value:=(Sender as TMenuItem).Caption;open;file://重新打开MainQuery end;end;********************************************************************** procedure Tmainform.SpeedButton1Click(Sender: TObject);Var s1,s2,s3,s4,s5 :String;file://设立5个变量以方便实现模糊查询 begin file://主窗口库存查询按钮事件 with datamoduleform.MainQuery do begin close;SQL.Clear;SQL.Add(‘select * from BookRecord‘);
SQL.Add(‘where BookID Like :BookID and BookName Like :Name and Author Like :Author and Publisher Like :pub and BookType Like :BookType‘);file://使用Like语句来实现模糊查询 if Edit1.Text<>‘‘ then s1:=‘%‘+Edit1.Text+‘%‘ else s1:=‘%‘;Parameters.ParamByName(‘BookID‘).Value:=s1;file://给变量s1赋值 if Edit2.Text<>‘‘ then s2:=‘%‘+Edit2.Text+‘%‘ else s2:=‘%‘;Parameters.ParamByName(‘Name‘).Value:=s2;file://给变量s2赋值 if Edit3.Text<>‘‘ then s3:=‘%‘+Edit3.Text+‘%‘ else s3:=‘%‘;Parameters.ParamByName(‘Author‘).Value:=s3;file://给变量s2赋值 if Edit4.Text<>‘‘ then s4:=‘%‘+Edit4.Text+‘%‘ else s4:=‘%‘;Parameters.ParamByName(‘Pub‘).Value:=s4;file://给变量s2赋值
if Edit5.Text <>‘‘ then s5:=‘%‘+Edit5.Text+‘%‘ else s5:=‘%‘;
Parameters.ParamByName(‘BookType‘).Value:=s5;file://给变量s2赋值 open;if FieldValues[‘BookID‘]=NULL file://判断是否找到记录 then begin Messagedlg(‘没有找到你所需要的记录!‘,mtInformation,[mbOK],0);Edit1.Text:=‘‘;Edit2.Text:=‘‘;Edit3.Text:=‘‘;Edit4.Text:=‘‘;Edit5.Text:=‘‘;close;SQL.Clear;SQL.Add(‘select * from BookRecord‘);file://这里相当于一个刷新功能 open;end;end;end;********************************************************************** procedure Tmainform.SpeedButton3Click(Sender: TObject);begin file://库存表刷新按钮事件 with datamoduleform.MainQuery do begin close;SQL.Clear;SQL.Add(‘select * from BookRecord‘);open;end;end;********************************************************************** procedure Tmainform.SpeedButton11Click(Sender: TObject);var PopupItem:TMenuItem;begin file://自动生成快捷按钮1的内容 with datamoduleform.BookQuery do begin file://从数据库中选择出版社类型 close;SQL.Clear;SQL.Add(‘select distinct Publisher from BookRecord‘);open;PopupMenu1:=TPopupMenu.Create(Self);file://自动生成快捷菜单 PopupMenu1.AutoHotkeys:=maManual;file://自定义热键 while Not Eof do begin file://根据出版社内容生成菜单子项 PopupItem:=TMenuItem.Create(Self);PopupItem.Caption:=FieldByName(‘Publisher‘).AsString;PopupMenu1.Items.Add(PopupItem);PopupItem.onClick:=Popup1Handler;file://确定菜单子项的点击事件 Next;end;end;PopupMenu1.Popup(384,67);file://在指定位置显示快捷菜单1 end;********************************************************************** procedure Tmainform.FormActivate(Sender: TObject);begin file://系统初始化,在进入mainform时自动添加数据源 mainform.DBGrid1.DataSource:=datamoduleform.MainSource;mainform.DBNavigator1.DataSource:=datamoduleform.MainSource;mainform.DBGrid2.DataSource:=datamoduleform.EmpSource;mainform.DBNavigator2.DataSource:=datamoduleform.EmpSource;mainform.DBGrid3.DataSource:=datamoduleform.ShopSource;mainform.DBNavigator3.DataSource:=datamoduleform.ShopSource;mainform.DBGrid4.DataSource:=datamoduleform.InSource;mainform.DBNavigator4.DataSource:=datamoduleform.InSource;mainform.DBGrid5.DataSource:=datamoduleform.OutSource;mainform.DBNavigator5.DataSource:=datamoduleform.OutSource;end;********************************************************************** procedure Tmainform.FormCreate(Sender: TObject);begin file://系统初始化,定义界面大小,以适应不同分辩率 Width:=800;Height:=600;end;********************************************************************** procedure Tmainform.Timer1Timer(Sender: TObject);begin file://在状态栏显示时间
StatusBar1.Panels[2].Text:=DateToStr(Date);StatusBar1.Panels[4].Text:=TimeToStr(Time);end;§5.4 入库、出库窗体模块的实现
图5.4 系统入库管理窗体
图5.5 系统出库管理窗体
procedure Tinoutform.SpeedButton4Click(Sender: TObject);begin file://入库管理查找按钮事件
with datamoduleform.BookQuery do file://入库查询处理 begin close;SQL.Clear;SQL.Add(‘select * from BookRecord where BookID=:BookID‘);Parameters.ParamByName(‘BookID‘).Value:=Edit13.Text;open;if FieldValues[‘BookID‘]<>NULL then begin Edit1.Text:=‘‘;
Edit1.ReadOnly:=true;Edit1.Color:=clMenu;Edit6.Text:=FieldValues[‘BookName‘];file://显示图书名
Edit6.ReadOnly:=true;Edit6.Color:=clMenu;file://设置显示框不可更改属性
Edit7.Text:=FieldValues[‘Author‘];
Edit7.ReadOnly:=true;Edit7.Color:=clMenu;Edit8.Text:=FieldValues[‘Publisher‘];Edit8.ReadOnly:=true;Edit8.Color:=clMenu;Edit9.Text:=FieldValues[‘PubDate‘];
Edit9.ReadOnly:=true;Edit9.Color:=clMenu;Edit10.Text:=FieldValues[‘Price‘];
Edit10.ReadOnly:=true;Edit10.Color:=clMenu;Edit11.Text:=FieldValues[‘BookType‘];
Edit11.ReadOnly:=true;Edit11.Color:=clMenu;Edit12.Text:=FieldValues[‘Number1‘];
Edit12.ReadOnly:=true;Edit12.Color:=clMenu;If FieldValues[‘Addation‘]<>NULL then Edit25.Text:=FieldValues[‘Addation‘]
else Edit25.Text:=‘‘;
Edit25.ReadOnly:=true;Edit25.Color:=clMenu;end else begin file://在没有查找到的情况下,清空所有显示框
Edit1.ReadOnly:=false;Edit1.Text:=‘‘;Edit1.Color:=clMenu;
Edit6.ReadOnly:=false;Edit6.Text:=‘‘;Edit6.Color:=clMenu;
Edit7.ReadOnly:=false;Edit7.Text:=‘‘;Edit7.Color:=clMenu;Edit8.ReadOnly:=false;Edit8.Text:=‘‘;Edit8.Color:=clMenu;
Edit9.ReadOnly:=false;Edit9.Text:=‘‘;Edit9.Color:=clMenu;
Edit10.ReadOnly:=false;Edit10.Text:=‘‘;Edit10.Color:=clMenu;
Edit11.ReadOnly:=false;Edit11.Text:=‘‘;Edit11.Color:=clMenu;Edit12.ReadOnly:=false;Edit12.Text:=‘‘;Edit12.Color:=clMenu;
Edit25.ReadOnly:=false;Edit25.Text:=‘‘;Edit25.Color:=clMenu;
MessageDlg(‘没有找到你所需要的记录!‘,mtInformation,[mbOK],0);
Edit13.Text:=‘‘;Edit13.SetFocus;end;end;with datamoduleform.InQuery do file://自动入库编号的获取 begin close;SQL.Clear;SQL.Add(‘select * from InRecord where InID>=All(select InID from InRecord)‘);
open;file://找到入库编号中最大的一个 Edit26.ReadOnly:=false;Edit26.Text:=FieldValues[‘InID‘]+1;file://最大的入库编号加1形成新的入库编号
Edit26.ReadOnly:=true;Edit26.Color:=clMenu;file://设置编号的不可更改性 end;end;********************************************************************** procedure Tinoutform.SpeedButton1Click(Sender: TObject);var s:integer;begin file://入库管理添加按钮事件 if Edit1.Text<>NULL then MessageDlg(‘请输入完整的入库信息和图书信息,然后单击确定按钮。‘,mtInformation,[mbok],0)else begin if(Edit2.Text=‘‘)or(Edit3.Text=‘‘)or(Edit4.Text=‘‘)or(Edit5.Text=‘‘)then begin MessageDlg(‘请输入完整的入库信息!‘,mtInformation,[mbok],0);Edit2.SetFocus;end else begin with datamoduleform.InQuery do file://将找到的图书信息显示 begin close;SQL.Clear;SQL.Add(‘insert into InRecord values(:InID,:BookID,:EmpID,:ShopID, :Number,:InDate)‘);file://向入库信息表中插入记录
Parameters.ParamByName(‘InID‘).Value:=Edit26.Text;file://向Edit框取值
Parameters.ParamByName(‘BookID‘).Value:=Edit13.Text;
Parameters.ParamByName(‘EmpID‘).Value:=Edit2.Text;
Parameters.ParamByName(‘ShopID‘).Value:=Edit3.Text;
Parameters.ParamByName(‘Number‘).Value:=Edit4.Text;
Parameters.ParamByName(‘InDate‘).Value:=Edit5.Text;execSQL;end;Edit12.ReadOnly:=False;S:=StrToInt(Edit12.Text)+StrToInt(Edit4.Text);file://计算入库后库存图书数量
Edit12.Text:=IntToStr(s);file://将修改后的库存图书数量显示 Edit12.ReadOnly:=true;with datamoduleform.BookQuery do file://修改库存记录中图书数量
begin close;SQL.Clear;SQL.Add(‘update BookRecord set Number1=:Number where BookID=:BookID‘);
Parameters.ParamByName(‘Number‘).Value:=s;
Parameters.ParamByName(‘BookID‘).Value:=Edit13.Text;execSQL;file://提交SQL语句
MessageDlg(‘记录已成功添加!‘,mtInformation,[mbOK],0);Edit13.SetFocus;end;end;end;end;********************************************************************** procedure Tinoutform.SpeedButton2Click(Sender: TObject);begin file://入库管理确定按钮事件
if(Edit2.Text=‘‘)or(Edit3.Text=‘‘)or(Edit4.Text=‘‘)or(Edit5.Text=‘‘)
or(Edit6.Text=‘‘)or(Edit7.Text=‘‘)or(Edit8.Text=‘‘)or(Edit9.Text=‘‘)
or(Edit10.Text=‘‘)or(Edit11.Text=‘‘)or(Edit25.Text=‘‘)then begin file://判断输入信息的完整性
MessageDlg(‘请输入所需的全部入库信息!‘,mtInformation,[mbok],0);Edit2.SetFocus;end else begin with datamoduleform.InQuery do file://入库信息添加 begin close;SQL.Clear;SQL.Add(‘insert into InRecord values(:InID,:BookID,:EmpID,:ShopID, :Number,:InDate)‘);file://向入库信息表中插入记录
Parameters.ParamByName(‘InID‘).Value:=Edit26.Text;
Parameters.ParamByName(‘BookID‘).Value:=Edit1.Text;
Parameters.ParamByName(‘EmpID‘).Value:=Edit2.Text;
Parameters.ParamByName(‘ShopID‘).Value:=Edit3.Text;
Parameters.ParamByName(‘Number‘).Value:=Edit4.Text;
Parameters.ParamByName(‘InDate‘).Value:=Edit5.Text;execSQL;end;with datamoduleform.BookQuery do begin close;SQL.Clear;file://在完成入库信息的添加后,修改库存记录 SQL.Add(‘insert into BookRecord values(:BookID,:BookName,:Author, :Publisher,:PubDate,:Price,:BookType,:Number,:Addration)‘);
Parameters.ParamByName(‘BookID‘).Value:=Edit1.Text;
Parameters.ParamByName(‘BookName‘).Value:=Edit6.Text;
Parameters.ParamByName(‘Author‘).Value:=Edit7.Text;
Parameters.ParamByName(‘Publisher‘).Value:=Edit8.Text;
Parameters.ParamByName(‘PubDate‘).Value:=Edit9.Text;
Parameters.ParamByName(‘Price‘).Value:=Edit10.Text;
Parameters.ParamByName(‘BookType‘).Value:=Edit11.Text;
Parameters.ParamByName(‘Number‘).Value:=Edit4.Text;
Parameters.ParamByName(‘Addration‘).Value:=Edit25.Text;execSQL;end;MessageDlg(‘记录添加成功!‘,mtInformation,[mbok],0);end;end;********************************************************************** procedure Tinoutform.SpeedButton11Click(Sender: TObject);begin file://新书入库按钮事件
Edit13.Text:=‘‘;Edit13.Color:=clMenu;
with datamoduleform.InQuery do file://自动入库编号的获取 begin close;SQL.Clear;SQL.Add(‘select * from InRecord where InID>=All(select InID from InRecord)‘);open;Edit26.Text:=FieldValues[‘InID‘]+1;
Edit26.ReadOnly:=true;Edit26.Color:=clMenu;end;with datamoduleform.BookQuery do file://自动图书编号的获取 begin close;SQL.Clear;SQL.Add(‘select * from BookRecord where BookID>=All(select BookID from BookRecord)‘);file://找到库存图书编号中最大的一个 open;Edit1.ReadOnly:=false;Edit1.Text:=FieldValues[‘BookID‘]+1;file://显示自动生成的图书编号
Edit1.ReadOnly:=true;Edit1.Color:=clMenu;end;Edit2.Text:=‘‘;Edit3.Text:=‘‘;Edit4.Text:=‘‘;Edit5.Text:=‘‘;Edit6.ReadOnly:=false;Edit6.Text:=‘‘;Edit6.Color:=clWindow;
Edit7.ReadOnly:=false;Edit7.Text:=‘‘;Edit7.Color:=clWindow;
Edit8.ReadOnly:=false;Edit8.Text:=‘‘;Edit8.Color:=clWindow;
Edit9.ReadOnly:=false;Edit9.Text:=‘‘;Edit9.Color:=clWindow;Edit10.ReadOnly:=false;Edit10.Text:=‘‘;Edit10.Color:=clWindow;
Edit11.ReadOnly:=false;Edit11.Text:=‘‘;Edit11.Color:=clWindow;
Edit12.ReadOnly:=false;Edit12.Text:=‘‘;Edit12.Color:=clMenu;
Edit25.ReadOnly:=false;Edit25.Text:=‘‘;Edit25.Color:=clWindow;end;procedure Tinoutform.SpeedButton22Click(Sender: TObject);var s:integer;begin file://出库管理确定按钮事件
if(Edit24.Text=‘‘)or(Edit27.Text=‘‘)or(Edit28.Text=‘‘)then begin MessageDlg(‘请输入完整的出库信息!‘,mtInformation,[mbok],0);Edit24.SetFocus;end else begin if Edit27.Text>Edit21.Text file://检查出库数量是否小于库存数量 then begin MessageDlg(‘库存中的图书数量不够!‘,mtInformation,[mbok],0);Edit27.Text:=‘‘;Edit27.SetFocus;end else begin with datamoduleform.OutQuery do begin close;SQL.Clear;SQL.Add(‘insert into OutRecord values(:OutID,:BookID,:EmpID, :Number,:OutTime)‘);file://添加出库记录
Parameters.ParamByName(‘OutID‘).Value:=Edit23.Text;Parameters.ParamByName(‘BookID‘).Value:=Edit14.Text;Parameters.ParamByName(‘EmpID‘).Value:=Edit24.Text;Parameters.ParamByName(‘Number‘).Value:=Edit27.Text;Parameters.ParamByName(‘OutTime‘).Value:=Edit28.Text;execSQL;end;Edit21.ReadOnly:=False;s:=StrToInt(Edit21.Text)-StrToInt(Edit27.Text);file://计算出库后库存图书数量
Edit21.Text:=IntToStr(s);file://显示出库后库存图书数量 Edit21.ReadOnly:=True;with datamoduleform.BookQuery do begin file://修改库存图书数量 close;SQL.Clear;SQL.Add(‘update BookRecord set Number1=:Number where BookID=:BookID‘);Parameters.ParamByName(‘Number‘).Value:=s;
Parameters.ParamByName(‘BookID‘).Value:=Edit14.Text;execSQL;end;MessageDlg(‘出库记录添加成功!‘,mtInformation,[mbok],0);Edit14.Text:=‘‘;Edit14.SetFocus;end;end;end;§5.5 查询功能的实现
查询功能包括员工信息查询,供应商信息查询,入库信息查询和出库信息查询。由于每一个功能的实现都差不太多,而且其窗体也差不太多,所以在这里只给出员工信息查询窗体及其源代码。
图5.6 员工信息查询窗体
procedure Tfindempform.SpeedButton1Click(Sender: TObject);Var s1,s2,s3 :String;begin file://员工记录查询窗体查找按钮事件 with datamoduleform.EmpQuery do begin close;SQL.Clear;SQL.Add(‘select * from Employee‘);
SQL.Add(‘where EmployeeID Like :EmpID and EmployeeName Like :Name and Grade Like :Grade‘);file://实现模糊查询功能 if Edit1.Text<>‘‘ then s1:=‘%‘+Edit1.Text+‘%‘ else s1:=‘%‘;Parameters.ParamByName(‘EmpID‘).Value:=s1;
if Edit2.Text<>‘‘ then s2:=‘%‘+Edit2.Text+‘%‘ else s2:=‘%‘;Parameters.ParamByName(‘Name‘).Value:=s2;if Edit3.Text<>‘‘ then s3:=‘%‘+Edit3.Text+‘%‘ else s3:=‘%‘;Parameters.ParamByName(‘Grade‘).Value:=s3;open;if FieldValues[‘EmployeeID‘]<>NULL
then findempform.Close file://在找到记录的情况下关闭查找窗口 else begin MessageDlg(‘没有找到你所需要的记录!‘,mtInformation,[mbOK],0);Edit1.Text:=‘‘;Edit2.Text:=‘‘;Edit3.Text:=‘‘;Edit1.SetFocus;close;SQL.Clear;SQL.Add(‘select * from Employee‘);file://刷新员工信息窗口 open;end;end;end;§5.6 系统登陆窗体模块的实现
由于系统登陆窗体中有一幅彩图,在这里不便给出,而只给出了系统的实现。var keyname: string;file://定义了一个全局变量,在key2中有调用 procedure Tkeyform.SpeedButton1Click(Sender: TObject);var s:string;file://登陆窗口登陆按钮事件 begin if(Edit1.Text=‘‘)then begin MessageDlg(‘清输入登陆姓名和密码!‘,mtInformation,[mbok],0);Edit1.SetFocus;end else begin datamoduleform.KeyTable.Active:=true;if not datamoduleform.KeyTable.Locate(‘KeyName‘,Edit1.Text,[])file://判断登陆名是否存在 then begin MessageDlg(‘登陆名错误,请重新输入!‘,mtInformation,[mbok],0);Edit1.Text:=‘‘;Edit1.SetFocus;end else begin with datamoduleform.KeyQuery do begin close;SQL.Clear;SQL.Add(‘select * from Key where KeyName=:KeyName‘);Parameters.ParamByName(‘KeyName‘).Value:=Edit1.Text;open;s:=FieldValues[‘KeyNo‘];end;if s<>Edit2.Text file://判断登陆密码是否正确 then begin MessageDlg(‘登陆密码错误,请重新输入!‘,mtInformation,[mbok],0);Edit2.Text:=‘‘;Edit2.SetFocus;end else begin keyname:=Edit1.Text;keyform.Hide;mainform.Show;mainform.WindowState:=wsMaximized;end;end;end;end;§5.7 用户管理功能的实现 5.7.1 用户管理主窗体
图5.7 用户管理主窗体 5.7.2 密码修改窗体模块的实现
图5.8 密码修改窗体
procedure Tkey2form.SpeedButton1Click(Sender: TObject);begin file://密码修改窗口修改按钮事件
if(Edit1.Text=‘‘)or(Edit2.Text=‘‘)or(Edit3.Text=‘‘)then begin MessageDlg(‘请输入完整的信息。‘,mtInformation,[mbok],0);Edit1.SetFocus;end else begin if Not datamoduleform.KeyTable.Locate(‘KeyNo‘,Edit1.Text,[])then begin MessageDlg(‘原密码输入错误,不能修改新密码!‘,mtInformation,[mbok],0);Edit1.Text:=‘‘;Edit2.Text:=‘‘;Edit3.Text:=‘‘;Edit1.SetFocus;end else begin if Edit2.Text<>Edit3.Text then begin MessageDlg(‘两次密码输入不同,请重新输入新密码!‘,mtInformation,[mbok],0);
Edit2.Text:=‘‘;Edit3.Text:=‘‘;Edit2.SetFocus;end else begin file://在数据库中修改密码 with datamoduleform.KeyQuery do begin close;SQL.Clear;SQL.Add(‘update key set KeyNo=:KeyNo where KeyName=:KeyName‘);Parameters.ParamByName(‘KeyName‘).Value:=keyname;Parameters.ParamByName(‘KeyNo‘).Value:=Edit2.Text;execSQL;MessageDlg(‘密码修改成功!‘,mtInformation,[mbok],0);key2form.Close;end;end;end;end;end;5.7.3 用户注册窗体模块的实现 图5.9 用户注册窗体
procedure Tkey3form.SpeedButton1Click(Sender: TObject);begin file://用户注删窗口注删按钮事件
if(Edit1.Text=‘‘)or(Edit2.Text=‘‘)or(Edit3.Text=‘‘)then begin MessageDlg(‘请输入完整的信息!‘,mtInformation,[mbok],0);Edit1.SetFocus;end else begin if datamoduleform.KeyTable.Locate(‘KeyName‘,Edit1.Text,[])file://判断用户名是否存在,系统不允许用户名重复 then begin MessageDlg(‘用户名已存在,请输入新的用户名和密码!‘, mtInformation,[mbok],0);Edit1.Text:=‘‘;Edit2.Text:=‘‘;Edit3.Text:=‘‘;Edit1.SetFocus;end else begin if Edit2.Text<>Edit3.Text then begin MessageDlg(‘您输入的两个密码不相同,请重新输入!‘,mtInformation,[mbok],0);
Edit2.Text:=‘‘;Edit3.Text:=‘‘;Edit2.SetFocus;end else begin with datamoduleform.KeyQuery do file://在数据库中添加该用户 begin close;SQL.Clear;SQL.Add(‘insert into Key values(:KeyName,:KeyNo)‘);Parameters.ParamByName(‘KeyName‘).Value:=Edit1.Text;Parameters.ParamByName(‘KeyNo‘).Value:=Edit2.Text;execSQL;end;MessageDlg(‘新用户添加成功,您可以继续添加用户,或按“取消”退出。‘,mtInformation,[mbok],0);
Edit1.Text:=‘‘;Edit2.Text:=‘‘;Edit3.Text:=‘‘;Edit1.SetFocus;end;end;end;end;5.7.4 用户注销窗体模块的实现
图5.10 用户注销窗体
procedure Tkey4form.SpeedButton1Click(Sender: TObject);var s:string;begin file://用户注销窗口注销按钮事件 if(Edit1.Text=‘‘)or(Edit2.Text=‘‘)
then MessageDlg(‘请输入完整的信息!‘,mtInformation,[mbok],0)else begin if Not datamoduleform.KeyTable.Locate(‘KeyName‘,Edit1.Text,[])file://判断用户名是否存在,用户名必须存在,才可以删除 then begin MessageDlg(‘您所输入的用户名不存在,请重新输入或按“取消”退出。‘, mtInformation,[mbok],0);Edit1.Text:=‘‘;Edit2.Text:=‘‘;Edit1.SetFocus;end else begin with datamoduleform.KeyQuery do begin close;SQL.Clear;SQL.Add(‘select * from Key where KeyName=:KeyName‘);Parameters.ParamByName(‘KeyName‘).Value:=Edit1.Text;open;s:=FieldValues[‘KeyNo‘];end;if s<>Edit2.Text file://判断该用户名下的密码是否正确 then begin MessageDlg(‘您所输入的密码不正确,请重新输入或按“取消”退出。‘, mtInformation,[mbok],0);Edit2.Text:=‘‘;Edit2.SetFocus;end else begin file://从数据库中删除该用户 with datamoduleform.KeyQuery do begin close;SQL.Clear;SQL.Add(‘delete from Key where KeyName=:KeyName‘);Parameters.ParamByName(‘KeyName‘).Value:=Edit1.Text;execSQL;end;MessageDlg(‘用户已成功删除,您可以继续删除用户,或按“取消”退出。‘, mtInformation,[mbok],0);Edit1.Text:=‘‘;Edit2.Text:=‘‘;Edit1.SetFocus;end;end;end;end;
结束语
本 系统是一个面向小型图书企业,具有一定实用性的数据库信息管理系统。它主要完成对图书仓库的一系列管理,包括入库、出库、库存以及员工和供应商信息管理。本系统采用当前流行的面向对象的开发工具—Delphi来完成整个系统的设计,在数据库的设计上利用了Access的便利性和实用性。
本系统具有 相当的实用功能。在查询方面,系统实现了多条件任意字段的模糊查询,同时在分类查询上实现了动态生成,系统可以自动识别用户不同的输入。在图书入库、出库 和库存三者之间建立了良好的链接关系,某一部分地修改均会自动引发系统对与其相关的部分进行连锁修改。在用户管理方面,系统较好地实现了用户注册,用户注 销和密码修改等各项功能。系统在设计过程中不可避免地遇到了各种各样的问题,由于整个系统完全都是由个人设计的,有关Delphi许多细节问题都要靠自己去摸索,加之本人水平有限,并没有完全地理解Delphi的强大功能,而且还存在着许多不足之处。如: ※ 受开发条件和开发时间的限制,本系统只利用了本地数据库Access,它同应用程序处于同一系统中,能存储的数据量也有一定限制,并没有发挥出Delphi其数据库方面的优势;
※ 报表打印功能尚不够全面完善,不能实现动态报表; ※ 在一些数据输入时没有及时的进行数据格式校验,不能保证数据输入的绝对正确性。
※ 由于时间关系,系统功能实现不够完善,使用不是很方便,比如,没有实现多条记录的连锁删除和添加以及数据的导入功能。
这些都是需要完善的地方,该系统离实际使用也还有相当的距离,需要我进行不断地补充和完善。
通过本次毕业设计我学到了不少新的东西,也发现了大量的问题,有些在设计过程中已经解决,有些还有待今后慢慢学习。只要学习就会有更多的问题,有更多的难点,但也会有更多的收获。
考 文 献
[1] 郑荣贵、黄平、谷会东,Delphi 6.0数据库开发与应用,中科多媒体电子出版社,2002 [2] 伍俊良,Delphi 6控件应用实例教程,北京希望电子出版社,2002 [3] 卢国俊,Delphi 6数据库开发,电子工业出版社,2002 [4] 边萌,Delphi 编程起步,机械工业出版社,2002 [5] 伍俊良,Delphi 6课程设计案例精编,中国水利水电出版社,2002 [6] 丁宝康,数据库原理,经济科学出版社,2000 [7] 陆丽娜,软件工程,经济科学出版社,2000
第二篇:图书仓库管理系统的设计
图书仓库管理系统的设计
摘 要
本系统主要完成对图书仓库的库存管理,包括图书入库、出库、库存,员工信息,供应商信息以及密码管理等六个方面。系统可以完成对各类信息的浏览、查询、添加、删除、修改、报表等功能。
系统的核心是入库、库存和出库三者之间的联系,每一个表的修改都将联动的影响其它的表,当完成入库或出库操作时系统会自动地完成库存的修改。查询功能也是系统的核心之一,在系统中即有单条件查询和多条件查询,也有精确查询和模糊查询,系统不仅有静态的条件查询,也有动态生成的条件查询,其目的都是为了方便用户使用。系统有完整的用户添加、删除和密码修改功能,并具备报表打印功能。
系统采用Microsoft Office中的Access 2000来设计数据库,并使用当前优秀的开发工具—Delphi 6.0,它有着最为灵活的数据库结构,对数据库应用有着良好的支持。
论文主要介绍了本课题的开发背景,所要完成的功能和开发的过程。重点的说明了系统设计的重点、设计思想、难点技术和解决方案。
关键字:数据库,SQL语言,Delph 6,数据库组件,仓库管理 目 录
第一章 引言 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„1 1.1 课题来源 „„„„„„„„„„„„„„„„„„„„„„„„„„1 1.2 开发工具的选择 „„„„„„„„„„„„„„„„„„„„„„„2 1.3 所做的主要工作 „„„„„„„„„„„„„„„„„„„„„„„3 第二章 数据库概论 „„„„„„„„„„„„„„„„„„„„„„„„„„4 2.1 数据库的发展 „„„„„„„„„„„„„„„„„„„„„„„„4 2.1.1 数据库的发展 „„„„„„„„„„„„„„„„„„„„„„4 2.1.2 数据库阶段的特点 „„„„„„„„„„„„„„„„„„„„5 2.1.3 数据库技术 „„„„„„„„„„„„„„„„„„„„„„„6 2.2 数据库理论基础 „„„„„„„„„„„„„„„„„„„„„„„7 2.2.1 数据库模型 „„„„„„„„„„„„„„„„„„„„„„„7 2.2.2 数据库体系结构 „„„„„„„„„„„„„„„„„„„„10 2.2.3 数据的独立性 „„„„„„„„„„„„„„„„„„„„„11 2.2.4 范式 „„„„„„„„„„„„„„„„„„„„„„„„„11 2.3 SQL语言基础 „„„„„„„„„„„„„„„„„„„„„„„13 2.3.1 SQL简介 „„„„„„„„„„„„„„„„„„„„„„„13 2.3.2 SQL查询 „„„„„„„„„„„„„„„„„„„„„„„13 2.3.3 SQL数据更新 „„„„„„„„„„„„„„„„„„„„„14 第三章数据库开发工具 „„„„„„„„„„„„„„„„„„„„„„„16 3.1 Delphi 6.0 简介 „„„„„„„„„„„„„„„„„„„„„„„16 3.2 Delphi 6.0 控件 „„„„„„„„„„„„„„„„„„„„„„„17 3.2.1 ADO数据访问组件 „„„„„„„„„„„„„„„„„„„17 3.2.2 数据控制类DataControl „„„„„„„„„„„„„„„„„18 3.2.3 数据访问类DataAccess „„„„„„„„„„„„„„„„„18 3.2.4 SQL语言在Delphi中的应用 „„„„„„„„„„„„„„„19 3.3 Access 简介 „„„„„„„„„„„„„„„„„„„„„„„„21 第四章 系统总体设计 „„„„„„„„„„„„„„„„„„„„„„„„23 4.1 系统需求分析 „„„„„„„„„„„„„„„„„„„„„„„23 4.2 系统概要设计 „„„„„„„„„„„„„„„„„„„„„„„25 4.2.1 系统结构设计 „„„„„„„„„„„„„„„„„„„„„25 4.2.2 数据库设计 „„„„„„„„„„„„„„„„„„„„„„27 4.2.2.1 ER图设计 „„„„„„„„„„„„„„„„„„„„27 4.2.2.2 数据库表格设计„„„„„„„„„„„„„„„„„„29 4.3系统详细设计„„„„„„„„„„„„„„„„„„„„„„„„34 第五章 系统应用程序设计 „„„„„„„„„„„„„„„„„„„„„„37 5.1 系统窗体模块组成„„„„„„„„„„„„„„„„„„„„„„37 5.2 数据模块窗体设置„„„„„„„„„„„„„„„„„„„„„„38 5.3 主窗体功能模块的实现„„„„„„„„„„„„„„„„„„„„39 5.4 入库、出库窗体模块的实现„„„„„„„„„„„„„„„„„„43 5.5 查询功能的实现„„„„„„„„„„„„„„„„„„„„„„„51 5.6 系统登陆窗体模块的实现„„„„„„„„„„„„„„„„„„„52 5.7 用户管理功能的实现„„„„„„„„„„„„„„„„„„„„„54 5.7.1 用户管理主窗体 „„„„„„„„„„„„„„„„„„„„54 5.7.2 密码修改窗体模块的实现 „„„„„„„„„„„„„„„„54 5.7.3 用户注册窗体模块的实现 „„„„„„„„„„„„„„„„55 5.7.4 用户注销窗体模块的实现 „„„„„„„„„„„„„„„„57 结束语 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„59 致谢 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„60 参考文献 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„„61 第一章 引 言 §1.1 课题来源
随着社会经济的迅速发展和科学技术的全面进步,计算机事业的飞速发展,以计算机与通信技术为基础的信息系统正处于蓬勃发展的时期。随着经济文化水平的显著提高,人们对生活质量及工作环境的要求也越来越高。书籍做为人类的精神食粮,在现代社会中越来越受到重视,大量的书籍出现在市场上,人们有了各种各样不同的选择。与此同时,为了管理大量的图书,图书仓库也大量的出现,仓库的管理问题也就提上了日程。随着图书的大量增加,其管理难度也越来越大,如何优化仓库的日常管理也就成为了一个大众化的课题。
在计算机飞速发展的今天,将计算机这一信息处理利器应用于仓库的日常管理已是势必所然,而且这也将为仓库管理带来前所未有的改变,它可以带来意想不到的效益,同时也会为企业的飞速发展提供无限潜力。采用计算机管理信息系统已成为仓库管理科学化和现代化的重要标志,它给企业管理来了明显的经济效益和社会效益。主要体现在:
极大提高了仓库工作人员的工作效率,大大减少了以往入出存流程繁琐,杂乱,周期长的弊端。基于仓库管理的全面自动化,可以减少入库管理、出库管理及库存管理中的漏洞,可以节约不少管理开支,增加企业收入。
仓库的管理的操作自动化和信息的电子化,全面提高了仓库的管理水平。
随着我国改革开放的不断深入,经济飞速的发展,企业要想生存、发展,要想在激烈的市场竞争中立于不败之地,没有现代化的管理是万万不行的,仓库管理的全面自动化、信息化则是其中极其重要的部分。为了加快仓库管理自动化的步伐,提高仓库的管理业务处理效率,建立仓库管理系统已变得十分心要。
入库、库存、出库还是现在企业图书仓库管理的常规基本模式,虽然,最近又出现了很多新的管理模式,如:基于零库存思想的沃尔玛特管理方式,但这些新的思想在中国大部分企业的管理中还是难以实现的。所以如何设计好仓库管理系统,尽可能地减少仓库管理的重复性和低效性就成为当前最为重要的问题。图书仓库管理的核心是入库、库存和出库之间的联系,如何处理好三者之间的关系是系统最为关键的部分。另外,员工信息和供应商信息管理也是仓库管理中一个必不可少的部分,它提供着与入库和出库相关的地一些信息,使得整个系统更加完整,更加实用。通过对仓库管理日常工作的详细调查,搜集了大量的资料,从系统结构的组织,功能的实现,技术的要求以及可行性等多方面进行考虑,认为本课题是一个适应现今图书仓库管理需求的计算机信息管理系统,具有一定的实际开发价值和使用价值。§1.2 开发工具的选择
自Java诞生以来,随着Internet技术的普及和应用需求的变化,以第四代语言为主的应用开发产品发生了较大的变化,它们不仅已成为人们开发应用的开发工具,而且很多产品已发展成为一种强有力的应用开发环境。这些新型的开发工具通常以一种集成软件包的形式提供给开发人员,被称为Studio(工作室)或Suite(程序组)。例如,微软的Visual Studio 6.0,Borland公司的Delphi 6.0等数据库辅助开发工具。
现在,市场上可以选购的应用开发产品很多,流行的也有数十种。目前在我国市场上最为流行、使用最多、最为先进的可用作企业级开发工具的产品有: Microsoft公司的Visual Basic 6.0版 Microsoft公司的Visual C++6.0版 Borland公司的Delphi 6.0版
在目前市场上这些众多的程序开发工具中,有些强调程语言的弹性与执行效率;有些则偏重于可视化程序开发工具所带来的便利性与效率的得高,各有各的优点和特色,也满足了不同用户的需求。然而,语言的弹性和工具的便利性是密不可分的,只有便利的工具,却没有弹性的语言作支持,许多特殊化的处理动作必需要耗费数倍的工夫来处理,使得原来所标榜的效率提高的优点失去了作用;相反,如果只强调程语言的弹性,却没有便利的工具作配合,会使一些即使非常简单的界面处理动作,也会严重地浪费程序设计师的宝贵时间。
而Delphi是一个非常理想选择。Delphi 6 是操作系统中快速应用开发环境的最新版本。它也是当前Windows平台上第一个全面支持最新Web服务的快速开发工具。无论是企业级用户,还是个人开发者,都能够利用Delphi 6 轻松、快捷地构建新一代电子商务应用。Delphi 6 是惟一支持所有新出现的工业标准的RAD环境,包括XML(扩展标记语言)/XSL(可扩展样式语言),SOAP(简单对象存取协议)和WSDL(Web服务器描述语言)等。Delphi 6 是可视化的快速应用程序开发语言,它提供了可视化的集成开发环境,这一环境为应用程序设计人员提供了一系列灵活而先进的工具,可以广泛地用于种类应用程序设计。在Delphi 6 的集成开发环境中,用户可以设计程序代码、运行程序、进行程序错误的调试等,可视化的开发方法降低了应用程序开发的难度。Delphi的基础编程语言是具有面向对象特性的Pascal语言,即Object Pascal。Object Pascal具有代码稳定、可读性好、编译速度快等优点,并将面向对象的概念移植到了Pascal语言中,使这种基础语言有了新的发展空间。
使用Delphi 6.0,我们几乎可以作任何事情,还可以撰写种各种类型的应用程序,动态链接库(DLL)、CON、或CORBA对象,CGI/ISAPI程序,Microsoft Back Office应用程序。程序的规模小到简单的个人数据库应用,大到复杂的企业的多层次分布式系统,都可以使用Delphi进行开发,其友好的集成开发界面,可视化的双向开发模式,良好的数据库应用支持高效的程序开发和程序运行,备受广大程序开发人员的好评。尤其是Delphi对数据库应用的强大支持,大大提高了数据库应用软件开发的效率,缩短了开发周期,深受广大数据库应用程序设计人员的喜爱。Delphi为数据库应用开发人员提供了丰富的数据库开发组件,使数据库应用开发功能更强大,控制更灵活,编译后的程序运行速度更快。§1.3 本文所做工作
引言部分介绍了本系统的课题来源以及对数据库开发工具的选择。
第二章介绍了数据库的发展,关系数据库,数据库体系结构,并系统介绍了SQL语言,为设计和理解应用程序做了铺垫。
第三章系统介绍了Delphi 6.0及其部分控件,SQL语言在Delphi 6.0中的应用,以及Access等。
第四章是本文的主体,按照软件工程的要求,从需求分析开始,经过概要设计最后到详细设计,完成对整个系统的设计。
第五章根据第四章的设计结果利用Access 2000和Delphi 6.0进行了具体的窗体和应用程序设计。
总结部分介绍了设计体会和编程体会,并指出了系统设计中的不足和改进的方向 第二章 数据库概论 §2.1 数据库的发展
数据库处理在信息系统的研究中一直是非常重要的主题,然而,近年来,随着World Wide Web(www.xiexiebang.com公司的TOTAL等
(3)关系模型。关系模型的主要是用二维表格结构表达实体集,用外键表示实体间联系。关系模型是由若干个关系模式组成的集合。关系模式相当于前面提到的记录类型,它的实例称为关系,每个关系实际上是一张二维表格。
关系模型和层次、网状模型的最大判别是用关键码而不是用指针导航数据,表格简单用户易懂,编程时并不涉及存储结构,访问技术等细节。关系模型是数学化模型。SQL语言是关系数据库的标准化语言,已得到了广泛的应用。20世纪70年代对关系数据库的研究主要集中在理论和实验系统的开发方面。80年代初才形成产品,但很快得到广泛的应用和普及,并最终取代了层次、网状数据库产品。现在市场上典型的关系DBMS产品有DB2、ORACLE、SYBASE、INFORMIX和微机型产品Foxpro、Access等。
关系模型和网状、层次模型的最大区别是:关系模型用表格数据而不是通过指针链来表示和实现实体间联系。关系模型的数据结构简单、易懂。只需用简单的查询语句就可对数据库进行操作。关系模型是数学化的模型,可把表格看成一个集合,因此集合论、数理逻辑等知识可引入到关系模型中来。关系模型已是一个成熟的有前途的模型,已得到广泛应用。
(4)面向对象模型。目前,关系数据库的使用已相当普遍,但是,现实世界中仍然存在着许多含有复杂数据结构的应用领域,例如,CAD数据、图形数据等,而关系模型在这方面的处理能力就显得力不从心。因此,人们需要更高级的数据库技术来表达这类信息。面向对象的概念最早出现在程序设计语言中,随后迅速渗透到计算机领域的每一个分支。面向对象数据库是面向对象概念与数据库技术相结合的产物。
面向对象模型能完整地描述现实世界的数据结构,具有丰富的表达能力,但模型相对较复杂,涉及的知识面也广,因此面向对象数据库尚未达到关系数据库那样的普及程度。
2.2.2 数据库体系结构
数据库的体系结构分三级:内部级(internal),概念级(conceptual)和外部级(external)。这个三级结构有时也称为“三级模式结构”,或“数据抽象的三个级别”,最早是在1971年通过的DBTG报告中提出,后来收入在1975年的美国ANSI/SPARC报告中。虽然现在DBMS的产品多种多样,在不同的操作系统支持下工作,但是大多数系统在总的体系结构上都具有三级模式的结构特征。从某个角度看到的数据特性称为“数据视图”(data view)。
外部级最接近用户,是单个用户所能看到的数据特性。单个用户使用的数据视图的描述称为“外模式”。
概念级涉及到所有用户的数据定义,是全局的数据视图。全局数据视图的描述称为“概念模式”。内部级最接近于物理存储设备,涉及到实际数据存储的结构。物理存储数据视图的描述称为“内模式”。
数据库的三级模式结构是数据的三个抽象级别。它把数据的具体组织留给DBMS去做,用户只要抽象地处理数据,而不必关心数据在计算机中的表示和存储,这样就减轻了用户使用系统的负担。三级结构之间往往差别很大,为了实现这三个抽象级别的联系和转换,DBMS在三级结构之间提供两个层次的映象(mappings):外模式/模式映象,模式/内模式映象。此处模式是概念模式的简称。
2.2.3 数据的独立性
由于数据库系统采用三级模式结构,因此系统具有数据独立性的特点。在数据库技术中,数据独立性是指应用程序和数据之间相互独立,不受影响。数据独立性分成物理数据独立性和逻辑数据独立性两级。(1)物理数据独立性
如果数据库的内模式要进行修改,即数据库的存储设备和存储方法有所变化,那么模式/内模式映象也要进行相当的修改,使概念模式尽可能保持不变。也就是对内模式的修改尽量不影响概念模式,当然,对于外模式和应用程序的影响更小,这样,我们称数据库达到了物理数据独立性。(2)逻辑数据独立性
如果数据库的概念模式要进行修改,譬如增加记录类型或增加数据项,那么外模式/模式映象也要进行相应的修改,使外模式尽可能保持不变。也就是对概念模式的修改尽量不影响外模式和应用程序,这样,我们称数据库达到了逻辑数据独立性。
现有关系系统产品均提供了较高的物理独立性,而对逻辑独立性的支持尚有欠缺,例如,对外模式的数据更新受到限制等。2.2.4 范式
建立起一个良好的数据指标体系,是建立数据结构和数据库的最重要的一环。一个良好的数据指标体系是建立DB的必要条件,但不是充分条件。我们完全可以认为所建指标体系中的一个指标类就是关系数据库中的一个基本表,而这个指标类下面的一个个具体指标就是这个基本表中的一个字段。但如果直接按照这种方式建库显然还不能算最佳。对于指标体系中数据的结构在建库前还必须进行规范化的重新组织。
在数据的规范化表达中,一般将一组相互关联的数据称为一个关系(relation),而在这个关系下的每个数据指标项则被称为数据元素(data element),这种关系落实到具体数据库上就是基本表,而数据元素就是基本表中的一个字段(field)。规范化表达还规定在每一个基本表中必须定义一个数据元素为关键字(key),它可以唯一地标识出该表中其它相关的数据元素。在规范化理论中表是二维的,它有如下四个性质:
在表中的任意一列上,数据项应属于同一个属性(如图中每一列都存放着不同合同记录的同一属性数据)。
表中所有行都是不相同的,不允许有重复组项出现(如图中每一行都是一个不同的合同记录)。在表中,行的顺序无关紧要(如图中每行存的都是合同记录,至于先放哪一个合同都没关系)。在表中,列的顺序无关紧要,但不能重复(如图中合同号和合同名谁先谁后都没关系,但二者不可重复或同名)。
在对表的形式进行了规范化定义后,数据结构还有五种规范化定义,定名为规范化模式,称为范式。在这五种范式中,一般只用前三种,对于常用系统就足够了。而且这五种范式是“向上兼容”的,即满足第五范式的数据结构自动满足一、二、三、四范式,满足第四范式的数据结构自动满足第一、二、三范式,„„,依此类推。
第一范式(first normal form,简称1st NF)就是指在同一表中没有重复项出现,如果有则应将重复项去掉。这个去掉重复项的过程就称之为规范化处理。在本文所讨论的开发方法里,1st NF实际上是没有什么意义的。因为我们按规范化建立的指标体系和表的过程都自动保证了所有表都满足1st NF。
第二范式(second normal form,简称 2nd NF)是指每个表必须有一个(而且仅一个)数据元素为主关键字(primary key),其它数据元素与主关键字一一对应。例如,在图l9.7中如果我们将合同号定义为主关键字(其它数据元素中的记录数据都有可能重名,故不能作为主关键字),故只要知道了一个合同记录的合同号,就可以唯一地在同一行中找到该合同的任何一项具体信息。通常我们称这种关系为函数依赖(functional depEndence)关系。即表中其它数据元素都依赖于主关键字,或称该数据元素唯一地被主关键字所标识。
第三范式(third normal form,简称 3rd NF)就是指表中的所有数据元素不但要能够唯一地被主关键字所标识,而且它们之间还必须相互独立,不存在其它的函数关系。也就是说对于一个满足了 2nd NF的数据结构来说,表中有可能存在某些数据元素依赖于其它非关键宇数据元素的现象,必须加以消除。
为防止数据库出现更新异常、插入异常、删除异常、数据冗余太大等现象,关系型数据库要尽量按关系规范化要求进行数据库设计。
§2.3 SQL语言基础 2.3.1 SQL简介
用户对数据库的使用,是通过数据库管理系统提供的语言来实现的。不同的数据库管理系统提供不同的数据库语言。关系数据库管理系统几乎都提供关系数据库标准语言——SQL。
SQL 的全称是Structured Query Language,即结构化查询语言。SQL语句可以从关系数据库中获得数据,也可以建立数据库、增加数据、修改数据。1986年ANSI采用SQL语言作为关系数据库系统的标准语言,后被国际化标准组织(ISO)采纳为国际标准。SQL语言使用方便、功能丰富、简洁易学,是操作数据库的工业标准语言,得到广泛地应用。例如关系数据库产品DB2、ORACLE等都实现了SQL语言。同时,其它数据库产品厂家也纷纷推出各自的支持SQL的软件或者与SQL的接口软件。这样SQL语言很快被整个计算机界认可。
SQL语言是一种非过程化语言,它一次处理一个记录集合,对数据提供自动导航。SQL语言允许用户在高层的数据结构上工作,而不对单个记录进行操作。SQL语言不要求用户指定数据的存取方法,而是使用查询优化器,由系统决定对指定数据存取的最快速手段。当设计者在关系表上定义了索引时,系统会自动利用索引进行快速检索,用户不需知道表上是否有索引或者有什么类型的索引等细节。
SQL语言可以完成许多功能,例如: ● 查询数据
● 在数据库表格中插入、修改和删除记录 ● 建立、修改和删除数据对象 ● 控制对数据和数据对象的存取 ● 确保数据库的一致性和完整性等 2.3.2 SQL查询
数据查询是关系运算理论在SQL语言中的主要体现,SELECT 语句是SQL查询的基本语句,当我们在对一个数据库进各种各样的操作时,使用的最多的就是数据查询,在以SQL为基础的关系数据库中,使用的最多的就是SELECT查询语句。SELECT语句的完整句法如下: SELECT 目标表的列名或列表达式序列 FROM 基本表和(或)视图序列 [WHERE 行条件表达式] [GROUP BY 列名序列] [HAVING 组条件表达式] [ORDER BY列名 [ASC│DEAC]„]
我在SELECT语句中还使用了大量的保留字和通配符以进行各种各样的条件查询。在系统中有大量的查询按钮,其使用了大量的查询语句,而且这些查询语句大部分使用的是模糊查询,所以大量的使用了模式匹配符LIKE(判断值是否与指定的字符通配格式相符)。在包含LIKE的查询语句中可以使用两个通配符:%(百分号):与零个或多个字符组成的字符串匹配;_(下划线):与单个字符匹配。系统中的条件判断往往包含多个条件,这时就需要使用逻辑运算符NOT、AND、OR(用于多条件的逻辑连接),谓词ALL以及保留字DISTINCT等等。做为SELECT语句还有很多的使用方法,这里就不再叙述。2.3.3 SQL数据更新
使用数据库的目的是为了有效地管理数据,而数据的插入、删除和修改则是必不可少的一个功能。在本系统中就大量地使用了数据插入、删除和修改这三种操作,现做一个简单地介绍。●数据插入
往数据库的基本表中插入数据使用的是INSERT语句,其方式有两种:一种是元组值的插入,另一种是查询结果的插入。在本系统中使用的是前一种方式,其句法如下: INSERT INTO 基本表名(列表名)VALUES(元组值)●数据删除
往数据库的基本表中删除数据使用的是DELETE语句,其句法如下: DELETE FROM 基本表名 [WHERE 条件表达式] 在些作一点说明,删除语句实际上是“SELECT * FROM 基本表名 [WHERE 条件表达式]”和DELETE操作的结合,每找到一个元组,就把它删除。此外,DELETE语句只能从一个基本表中删除元组,WHERE子句中条件可以嵌套,也可以是来自几个基本表的复合条件。●数据修改
当需要修改基本表中元组的某些列值时,可以用UPDATE语句实现,其句法如下: UPDATE基本表名
SET列名=值表达式[,列名=值表达式„] [WHERE条件表达式] 在Delphi中使用SQL语句是很方便的,一般来说,都是通过TQuery组件来使用SQL语言的。有一点要进行说明,虽然通过TQuery组件来使用SQL语言很方便,但考虑到自己对不同组件的理解程度、个人习惯以及其它各个方面,在本系统中我采用的是ADO组件来对数据库进行操作。最简单的方法比如在TADOQuery组件的SQL属性中就可以键入SQL语句,至于详细的使用方法在后面进行介绍。
第三章 数据库开发工具 §3.1 Delphi 6.0 简介
Delphi类可以粗略地分成两部分:一部分是组件类,这些组件类通常以某种方式出现在组件面板上,当用户从组件面板上点取一个类的图标后,在程序中就自动生成了该类的对象(非可视组件除外);另一部分是功能类,这此功能类的对象通常出现在程序代码中,起着不可代替的作用,但是这些功能类在组件面板上是找不到的。在Delphi中,每一个类的祖先都是Tobject类,整个类的层次结构就像一棵倒挂的树,在最顶层的树根即为Tobject类。这样,按照面向对象编程的基本思想,就使得用户可用Tobject类这个类型代替任何其它类的数据类型。实际上在Delphi的类库中,Tobject类派生出了为数相当众多的子类,它们形成了一个庞大的体系,通常情况下,如果不自行开发组件,就不必了解整个类的体系结构,只用到类层次树的叶结点就足够了。凡是做过程序开发的人都知道从来没有单纯的数据应用程序,也就是说,数据库应用程序必须和用户界面(可以是图形界面,也可以是命令接口)元素相结合,只讲界面或只讲数据库本身都构不成数据库应用程序,因而用Delphi 6.0开发数据库应用程序就隐含着界面开发。Delphi6中的VCL组件可用图3-1来说明。组件在Delphi程序的开发中是最显眼的角色。大家知道,在编写程序时一般都开始于在组件面板上选择组件并定义组件间的相互作用。但也有一些组件不在组件面板上,例如Tform和Tapplication(典型的非可视组件)。组件是Tcomponents派生出来的子类,可以流的形式存放在DFM文件中,具有事件和Publish属性。
窗口组件类是窗口化的可视化组件类,在Delphi的类库中占有最大的份额。在实际编程中,窗口组件类的对象都有句柄,可以接受输入焦点和包含其它组件。
图形组件与窗口组件并列,是另一大类组件。图形组件不是基于窗口的,因而不能有窗口句柄,不能接受输入焦点和包含其它组件。从图8-43中可以看出,图形组件的基类是TgraphicControl,在实际编程中,它们必须寄生于它们的宿主——窗口组件类的对象,由它们的拥有者负责其显示,而且它们还能触发一些和鼠标活动相关的事件。图形控件最典型的例子是Tlabel和TspeedButton。由此可以看出图形组件的功能很弱,有读者会问图形组件的用处何在呢?其实使用图形组件的最大好处在于节省资源,正是因为它们的功能较弱,所以使用的系统资源就要少。在一个应用程序中,如果能在不影响其功能的前提下合理大量地使用图形组件,将会大减少程序对系统资源的消耗。
非可视组件是与可视组件相并列的另一类组件,非可视组件在程序运行中是不可见的(除各种对话框组件之外,事实上有人认为对话框组件不能归入非可视组件,应该是另一种介于可视与非可视之间的组件)。§3.2 Delphi 6.0 控件
用Delphi6开发数据库应用,重点是和各种数据库组件打交道,当然也要使用其它的一些组件,现在就我在系统设计中所使用的重要组件给与简单介绍。3.2.1 ADO数据访问组件
ADO数据对象(Active Data Objects)实际是一种提供访问各种数据类型的链接机制。ADO设计为一种极简单的格式,通过ODBC的方法同数据库接口中,可以使用任何一种ODBC数据源,即不止适合于SQL Server、Oracle、Access等数据库应用程序,也适合于Excel表格、文本文件、图形文件和无格式的数据文件。ADO是基于OLE-DB之上的技术,因此ADO通过其内部的属性和方法提供统一的数据访问接口方法。ADO使您的客户端应用程序能够通过OLE DB提供访问和操作在数据库服务器中的数据。ADO支持用于建立C/S和Web的应用程序的主要功能。其主要优点是易于使用、高速度、低内存支出和占用磁盘空间较少。ADO同时具有远程数据服务(RDS)功能,通过RDS可以在一次往返过程中实现将数据从服务器移动到客户端应用程序和Web页、在客户端对数据进行处然后将更新结果返回服务器的操作。
Delphi 6.0继续对Microsoft的ADO访问能力的支持。这种能力是通过一组新组件实现的,这些组件是在企业版的ADO组件页中,在组件面版的ADO页上可以找到这些组件。利用在前面章节提到的TdataSet抽象类,ADO组件可以不通过BDE而直接实现ADO连接。这意味着只需要很少的代码就可以实现该连接并且性能得到提高。
利用ADO数据访问组件,可以只使用ADO结构与数据库取得联系并对其中的数据进行操作,而在这些过程中完全不需要使用BDE。大多数的ADO连接和数据集组件都是与基于BDE的连接和数据集组件相类似的。TADOConnection组件与基于BDE的应用程序中的Tdatabase组件类似。TADOTable与Ttable,TADOQuery与Tquery,以及TADOStoreProc和TstoredProc之间都具有这种类似的对应关系。使用这些ADO组件的方式与我们常使用的数据访问组件(基于BDE)都有许多相同之处。TTADODataSet没有直接的BDE对应组件,但它提供了许多与Ttable和Tquery相同的功能。同样,TADOCommand也没有相对应的BDE组件,它是在Delphi/ADO环境中完成特定功能的组件。Delphi 6.0通过ADO数据集访问组件,可以不借助BDE数据引擎而是通过微软的OLEDB来访问更为广泛的数据库中的数据。ADO数据集访问组件与常用的数据访问组件是并列的关系。
在系统中我主要使用的是ADOTablet和ADOQuery两个组件。3.2.2 数据控制类DataControl 数据控制类负责数据库数据的显示,并把用户对数据的修改传回。这里的绝大多数组件,如DBText, DBEdit, DBMemo, DBImage, DBListBox, DBComboBox, DBCheckBox, DBRadioGroup, DBLookupListBox, DBLookupCombox, DBCtrGrid的功能和对应的非数据感知组件相同,如TEdit框,TRadioGroups单选按钮组等,只不过在显示数据库数据时要用而已。在系统中主要使用数据网格控件DBGrid和数据库导航器控件DBNavigator。3.2.3 数据访问类DataAccess 数据库应用系统中数据访问是一个首要问题,包括单用户和 C/S系统,都必须联系一些数据库和数据表文件。Delphi 6 提供了专门用于数据访问的基类控件。主要包括数据源控件DataSource、客户数据集控件ClientDataSet、数据集提供器控件DataSetProvider等等。
Tdatabase:当一个基于BDE的数据库应用程序需要一个永久数据库连接时,需要定制向一个数据库服务器的连接时,需要事务控制和特殊的数据库别名时就得用到Tdatabase对象。特别是当连接到一个远程的SQL数据库服务器时,如果要利用BDE进行数据库事务处理,那么,TDatabase对象的威力就体现出来了。在一个应用程序中为每一个数据库连接显示的声明Tdatabase对象要根据需要而定,不是必需的。对一个数据库连接,如果没有显示的声明并实例化TDatabase对象,系统就会产生一个带有默认属性的TDatabase对象。
TdataSource对象用于在DataSet对象(包括Tquery,TstoredProc,Ttable等)和数据感知组件之间提供一个连接的纽带,以便在窗体上显示数据库中的数据,在数据库中导航定位与编辑数据集中的数据。如果一个DataSet对象中的数据想在数据感知组件中显示和修改,它就必须和TdataSource对象相联系。同样,一个数据感知组件如果想和数据源相联系以便显示和操纵数据,就必须以TDataSource对象为中介。
用Delphi6作数据库应用开发概括来说如下:先利用数据存取组件和实际的数据库建立连接,并用Tsession对象和Tdatabase对象管理这些连接。然后以Tdatasource对象为中介,用数据感知组件向用户显示数据库的内容并接受用户的查询和修改等操作。3.2.4 SQL语言在Delphi中的应用
在Delphi中使用SQL语言非常方便,一般来说,都是通过Tquery组件来使用SQL语言的。可以在TQuery组件的SQL属性中设置SQL语句。设计程序时,在该组件的属性对话框中选择SQL属性,单击带省略号的按钮,就可以打开String List Editor对话框,然后我们就可以在对话框中添加SQL语句。还可以使用Delphi的SQL Builder来自动生成SQL语句,这样可以避免手工编写SQL而可能造成的语法错误。
静态SQL语句在程序设计时便已固定下来,它不包含任何参数和变量。
动态SQL语句,也被称作参数化的语句,在其中间包含着表示字段名或表名的参数,例如下面的语句是一条动态SQL语句:
Select * From Students Where StudentCode =: StudentCode;其中的变量StudentCode便是一个参数变量,它由一个冒号引导,在程序运行过程中,必须要为该参数赋值,该条SQL语句才能正确执行,每次运行应用程序时可以为该参数变量赋予不同的值。为参数赋值有三种方法:
①根据参数在SQL语句中出现的顺序,设置TQuery部件的Params属性值为参数赋值。②直接根据SQL语句中各参数的名字,调用ParamByName方法来为各参数赋值。
③将TQuery部件的DataSource属性设置为另一个数据源,这样将另一个数据源中与当前TQuery部件的SQL语句中的参数名相匹配的字段值赋给其对应的参数。利用这种方法也能实现所谓的连接查询,创建主要—明细型数据库应用。
在程序运行过程中,要想设置TQuery部件的SQL属性,必须首先调用Close方法,关闭TQuery部件,然后再调用Clear方法清除SQL属性中现存的SQL命令语句,最后再调用Add方法为SQL属性设置新的SQL命令语句。例如: Query1.Close {关闭Query1)Query1.SQL.Clear {清除SQL属性中的SQL命令语句} Query1.SQL.Add(„Select * From Students„);Query1.SQL.Add(„ Where Name =“Lucy” „);
在为TQuery部件设置SQL属性时调用Close方法总是很安全的,如果TQuery部件已经被关闭了,调用Close方法时不会产生任何影响。在应用程序中为SQL属性设置新的SQL 命令语句时,必须要调用Clear方法以清除SQL属性中现存的SQL命令语句,如果不调用Clear方法,便调用Add方法向SQL属性中设置SQL命令语句,那么新设置的SQL命令语句会追加在现存SQL命令语句后面,在程序运行时常常会出现出乎意料的查询结果甚至程序无法运行下去。在这里要特别注意的,一般情况下TQuery部件的SQL属性只能包含一条完整的SQL语句,它不允许被设置成多条SQL语句。当然有些数据库服务器也支持在TQuery部件的SQL属性中设置多条SQL语句,只要数据库服务器允许这样,我们在编程时可以为 SQL 属性设置多条SQL语句。
在为TQuery部件设置完SQL属性的属性值之后,也即编写好适当的SQL程序之后,可以有多种方式来执行SQL程序。
在设计过程中,设置完TQuery部件的SQL属性之后将其Active属性的值置为True,这样便可以执行SQL属性中的SQL程序,如果应用中有与TQuery部件相连的数据浏览部件(如TDDGrid TDBEdit等)那么在这些数据浏览部件中会显示SQL程序的执行结果。
在应用程序运行过程中,通过程序调用TQuery部件的Open方法或ExecSQL 方法可以执行其SQL属性中的SQL程序。Open方法和ExecSQL方法是不一样的。Open方法只能用来执行SQL语言的查询语句(Select命令),并返回一个查询结果集,而ExecSQL方法还可以用来执行其它常用的SQL语句(如INSERT, UPDATE, DELETE等命令),例如: Query1.Open(这样会返回一个查询结果集)如果调用Open方法,而没有查询结果时,会出错。此时应该调用ExecSQL 方法来代替Open方法。如:
Query1.ExecSQL(没有返回结果)当然在设计应用程序时,程序设计人员是无法确定TQuery部件中的SQL 语句是否会返回一个查询结果的。对于这种情况应当用Try…Except模块来设计程序。在 Try 部分调用Open方法,而在Except部分调用ExceSQL方法,这样才能保证程序的正确运行。
Delphi中用ADOQuery来使用SQL语句同样十分方便。在ADOQuery组件中首先通过ConnectionString属性值来联接数据源,然后就通过双击SQL…属性值来写入SQL语句。在Delphi中调用数据库,就可以调用ADOQuery组件,通过修改其中的SQL…属性中的SQL语句来实现对数据库的各项操作。
值得注意的是,ADOQuery组件只有在激活的情况下才可以被正确地使用,这样就提出了一个问题,也就是说,在每次修改ADOQuery组件的SQL…属性时都必须先行进行关闭,待清除掉SQL…中所有的SQL语句后才可以添加新的SQL语句。而且,在每一次修改完成以后,还应该记得重新将ADOQuery激活。其它的使用方法与TTQuery有许多的相似之处。§3.3 Access 简介
建立一个数据库我们有多种选择,现在市场上有各种各样的数据库,而且每一种数据库都有其自身的特点,不能说哪一种更好,只能在其中寻找一种能更好地适应系统需求、更好地满足用户的要求以及适应开发人员的习惯。在本系统中,做为图书仓库管理系统是一个比较小的应用系统,它所产生和处理的数据量也比较小。因此,没有必要使用像SQL Server和Oracle这样的大型数据库。我首先想到的数据库是Borland公司的Paradox数据库。另外,Microsoft Office中的Access数据库在计算机上的应用比较普及,是开发小型数据库系统的比较理想的选择,所以,在本系统中我选择了Access数据库。
Access做为一个数据库管理系统,它被集成在Microsoft Office中。Access数据库处理的基本结构,采取关系型数据库模式。与其他的数据库系统相比,Access更加简单易学,一个普通的计算机用户可以很快地掌握它。Access 2000的功能十分强大,利用它可以方便地实现对信息保存、维护、查询、统计、打印、交流、发布,而且它可以十分方便地与Office其他组件交流数据,这些功能对一个一般用户而言已经足够了。第四章 系统总体设计
软件系统的总体设计大约要经历可行性分析和项目开发计划,需求分析,概要设计,详细设计,编码,测试以及维护等七个阶段。可行性分析和项目开发计划在前面已经叙述,下面所要做的是进行软件需求分析,概要设计和详细设计。编码过程将在下一节论述,而测试和维护过程不在本文叙及。
§4.1 系统需求分析
在经过前一阶段的分析之后,我确定了我的开发课题为图书仓库管理。现在所要做的是要准确定义系统必须做什么以及系统必须具备的功能。
软件需求分析中我采用结构化分析方法(Structured Analysis,简称SA),SA是面向数据流进行需求分析的方法,像所有的软件分析方法(如面向对象分析方法、IDEF方法等等)一样,SA也是一种建模活动,它使用简单易读的符号,根据软件内部数据传递、变换的关系,自顶向下逐层分解,描绘满足功能要求的软件模型。
在系统中我采用数据流图(DFD)这种半形式化的描述方式表达需求。它是一种功能模型,以图形的方式描绘数据在系统中流动和处理的过程,只反映系统必须完成的逻辑功能。它有四种基本图形符号:
◆ →:箭头,表示数据流; ◆ 〇:圆或椭圆,表示加工; ◆ ═:双杠,表示数据存储;
◆ □:方框,表示数据的源点或终点。
为了表达较为复杂问题的数据处理过程,用一张数据流图是不够的,要按照问题的层次结构进行逐步分解,并以一套分层的数据流图反映这种结构关系。在这里我一共使用了三层数据流图,即顶层图,0层图和1层图(也是底层图)。
在多层数据流图中,顶层流图仅包含一个加工,它代表被开发系统,它的输入流是该系统的输入数据了,输出流是该系统的输出数据;底层流图是指其加工不需要再做分解的数据流图,中间层流图表示对其上层父图的细化,它的每一步加工可能继续细化成子图。经过对系统的分析首先得到系统的顶层DFD,如下: 一步细化得到系统的0层DFD,如下:
再进一步细化每一个数据加工功能,得到系统的1层DFD图。
在这里只给出有关入库管理和出库管理的1层数据流图,它们是系统的关鍵部分,也是主要的部分。通过以上对数据流图的分析之后,我们已大体地了解了系统的功能和目标,接下来所要做的就是系统功能模块的划分和数据库的设计,也就是系统的概要设计。§4.2 系统概要设计 在软件需求分析阶段,搞清楚了软件“做什么”的问题,形成了目标系统的逻辑模型。现在我们所要做的就是要把软件“做什么”的逻辑模型变换为“怎么做”的物理模型,即着手实现软件的需求。首先,我们需要描述的是系统的总的体系结构。4.2.1 系统结构设计
系统的概要设计中最重要的就是系统的模块化。模块化是指解决一个复杂问题时自项向下逐层把软件系统划分成若干个模块的过程。每个模块完成一个特定的功能,所有的模块按某种方法组织起来,成为一个整体,完成整个系统所要求的功能。
将系统划分为多个模块是为了降低软件系统的复杂性,提高可读性、可维护性,但模块的划分不能是任意的,应尽量保持其独立性。也就是说,每个模块只完成系统要求的独立的子功能,并且与其他模块的联系最少且接口简单,即尽量做到高内聚低耦合,提高模块的独立性,为设计高质量的软件结构奠定基础。
在系统的概要设计中我采用结构化设计(Structure Design,简称SD),SD以需求分析阶段产生的数据流图DFD为基础,按一定的步骤映射成软件结构。我首先将整个系统化分为几个小问题,小模块,在系统中,我设计了用户管理、库存管理、入库管理、出库管理、员工管理和供应商管理6个小模块。然后,进一步细分模块,添加细节。比如,用户管理我又将其分为用户注册、用户注销、密码修改;库存管理分为库存记录查询、库存记录修改、库存记录打印等等。以下就是系统的结构图:(在这里为了表达方便我将结构图分开来表达。)
在得到系统的第一层功能模块图后,经过进一步地细化,得一系统的子功能模块图: 4.2.2 数据库设计
在信息世界中,信息从客观事物出发流经数据库,通过决策机构最后又回到客观世界,信息的这一循环经历了三个领域:信息世界,数据世界,现实世界。现实世界的事物反映到人的头脑中,人的大脑对它有个认识过程,经过分析(选择、命名、分类等)进入信息世界。这些信息再进一步加工、编码,然后进数据世界,而软件系统的开发工作需要考虑这两个方面的问题,也就是要考虑系统开发所需要的数据,以及如何对这些数据进行操作。这两个问题贯穿了整个软件系统的开发过程,这也就是数据库的设计问题,软件设计的一个核心。4.2.2.1 ER图设计
在系统设计的开始,我首先考虑的是如何用数据模型来数据库的结构与语义,以对现实世界进行抽象。目前广泛使用的数据模型可分为两种类型,一种是独立于计算机系统的“概念数据模型”,如“实体联系模型”;另一种是直接面向数据库逻辑结构的“结构数据模型”。在本系统中我采用“实体联系模型”(ER模型)来描述数据库的结构与语义,以对现实世界进行第一次抽象。ER模型直接从现实世界抽象出实体类型及实体间联系,然后用ER图来表示数据模型。它有两个明显的优点:接近于人的思维,容易理解;与计算机无关,用户容易接受。但ER模型只能说明实体间语义的联系,不能进一步说明详细的数据结构,它只是数据库设计的第一步。ER图是直观表示概念模型的工具,它有四个基本成分: ◆ 矩形框,表示实体类型(考虑问题的对象)。◆ 菱形框,表示联系类型(实体间的联系)。
◆ 椭圆形框,表示实体类型和联系类型的属性。对于关键码的属性,在属性名下划一横线。◆直线,联系类型与其涉及的实体类型之间以直线连接。
本系统为图书仓库管理,主要管理图书的入库、出库以及库存等事项。仓库根据需要可以查询图书供应商的信息,同时还需要了解在入库和出库中员工的参与情况。依据仓库管理的实际情况,考虑了多方面的因素以后,确定系统的ER图如下:
(为了表达的方便,在这里我没有在一张图上表达出所有的关系,而是用一张总体ER图,和几张实体属性关系图来表达数据库的结构。)
在该数据库中,我设计了三个实体,分别是库存、员工和供应商以及两个联系类型入库和出库。在本系统中库存是核心,也是基本,没有了库存其它的也就没有什么意义了。员工记录的添加是考虑到责任问题,也就是说,在仓库管理的实际运用中,出现了责任不清的现象,特别是由于仓库的进出图书数量都比较大时产生了一系列问题,所以在设计数据库时,我特别考虑到这一点,加入了员工记录这一实体。供应商信息的添加主要出于对图书来源问题的思考。通过添加供应商信息可以比较清楚地了解图书的进货渠道,从图书的质量到供应商的信誉都可以进行了解,同时可以为以后的图书进购提供一定有用的信息。
入库联系类型将库存信息、供应商信息和员工信息联系在一起,可以方便地实现三个实体之间的联接,而出库联系类型则将库存信息和员工信息较好地联接起,同时这两个联系类型又都具有各自特有的属性。
下面就是各实体及联系类型的属性图:(带#号的属性为关键字段)4.2.2.2 数据库表格设计 在完成系统的ER图之后,需要将ER模型转化为关系模型,也就是说,要设计出数据库所需要的表格。在这里,我选用的是关系数据库。因为关系数据库中的二维表格可以很清楚地描述数据之间的联系。
在这里不得不提到一个概念——范式。其实在上一节的ER图设计中,已经运用了范式的思想,不仅如此,在数据库的表格设计中更离不开范式的思想,它是数据库设计的基础,如果不注意这个问题将会导致一系列问题的出现。
我在系统中定义的表格都严格地按照范式的思想和要求去完成,数据库中的所有表格都达到了三范式的要求。根据系统ER图,针对本系统的特点,在对所搜集的数据进行规范化之后,定义了如下六张表格,分别是库存信息表,入库信息表,出库信息表,员工信息表,供应商信息表和密码信息表。通过对这六张表格的操作可以较好地完成系统设计的各项功能,六张表格之间有着不同程度的联系。(说明:在以下数据表中,K代表主键,#代表外键,字段值不为空。)BookRecord 表(库存信息表)
字段名称 数据类型 说明 K BookID 数字 图书编号 BookName 文本 图书名 Author 文本 作者 Publisher 文本 出版社 PubDate 日期/时间 出版日期 Price 货币 价格 BookType 文本 图书类型 Number1 数字 库存数量 Addation 文本 备注 图4.13 库存信息表
库存信息表主要用于记录仓库中现存放的所有图书的详细信息,包括图书编号、书名、作者、出版社、图书类型等有关图书的各类信息,它即是该数据库的主表,也是系统主界面的主要内容。在该表中图书编号是主键,它按图书入库的先后次序来编写,每当有图书入库,系统自动给出图书编号,这样我们按图书编号来查找图书是比较方便的。考虑到编号比较难于记忆,所以使用了出版社和图书类型两个字段,在系统中我提供了出版社和图书类型的分类查找,而且全部采用自动生成,每当系统中有新的出版社类型和图书类型,弹出菜单会自动添中新类型,这样就可以比较方便地实现按出版社和按图书类型查找。此外,库存数量也是一个比较关键的字段,该字段是在系统初始化时就给定的,每当有图书入库或出库操作,系统就会自动修改图书的库存数量,以保持数据的一致性。做为备注有一点说明,我的数据库中备注的数据类型是文本,而不是备注类型,主要考虑到该字段的长度并不大,而且在Delphi中文本数据类型的处理也比较方便一点。Employee 表(员工信息表)
字段名称 数据类型 说明 K EmployeeID 数字 员工编号 EmployeeName 文本 员工姓名 Sex 文本 性别
BornDate 日期/时间 出生日期 Grade 文本 职称
WorkDate 日期/时间 工作日期 Telephone 文本 联系电话 Address 文本 联系地址
图4.14 员工信息表
员工信息表主要用于记录有关员工的各类信息,包括姓名、职称、出生日期、联系电话、联系地址等。它主要用来为系统提供员工的有关信息,因为在系统中,入库和出库操作均与员工有着一定的联系,在查询入库信息和出库信息时,有时需要查找有关此项记录有关的员工信息,在系统中我是通过入库记录与员工记录(出库记录和员工记录)之间的联接查询来完成的。另外,作为一个仓库也有必要了解其所属员工的一些基本情况,以便查询。Shopkeeper 表(供应商信息表)
字段名称 数据类型 说明 K ShopkeeperID 数字 供应商编号 ShopkeeperName 文本 供应商姓名 Address 文本 地址 PostNo 数字 邮编
OfficePhone 文本 办公电话 HomePhone 文本 住宅电话 Email 文本 E-mail PayType 文本 付款方式
图4.15 供应商信息表
供应商信息表主要用于记录有关供应商的各类信息,包括姓名、地址、电话、付款方式等。它主要用来为系统提供供应商的有关信息,在系统中入库记录是与供应商记录相联系的,通过入库记录可以查找相关的供应商信息。在供应商信息中,考虑当实际情况,我特别加入了Email和付款方式这两个字段,因为在当今信息世界中,多种多样的通讯方式和多种多样的付款方式是必然的,是数据库中必须与以记录。
InRecord 表(入库信息表)
字段名称 数据类型 说明 K InID 数字 入库编号 # BookID 数字 图书编号 # EmployeeID 数字 员工编号 # ShopkeeperID 数字 供应商编号 Number 数字 入库数量 BuyDate 日期/时间 入库日期
图4.16 入库信息表
OutRecord 表(出库信息表)
字段名称 数据类型 说明 K OutID 数字 出库编号 # BookID 数字 图书编号 # EmployeeID 数字 员工编号 Number2 数字 出库数量 OutDate 日期/时间 出库日期 图4.17 出库信息表
入库信息表主要用于记录有关入库的详细信息,包括入库数量、入库日期以及图书、员工、供应商三方的编号,以便查询。出库信息表主要用于记录有关出库的详细信息,包括出库数量、出库日期以及图书、员工的编号。出库信息表和入库信息表一样,其实它们都属于联系类型,系统通过这两个表可以联接上其它的表为用户提供多种条件的联接查询。值得提出的一点是入库记录和出库记录的添加不仅仅是单表操作,由于它们都与库存记录相联系,所以,无论您是添中入库记录还是添加出库记录,都必须同时修改库存记录,以保持数据的一致性,否则将引发系统出错而这些我都让其在系统中自动完成。无论您是添加入库记录,还是添加出库记录,系统都将自动修改库存中图书的数量,而且,在您出库的数量大于库存数量时,系统还会自动提示错误,这样就可以防止一定错误的发生。
在入库信息表和出库信息表中我还定义了几个外键,它提供了一种表示几个关系联系的方法。比如,系统中通过在入库信息表中定义的外键 BookID、EmployeeID和ShopkeeperID可以将库存信息表、员工信息表和供应商信息表联系在一起,从而方便地实现联接查询,而且,引入外键的定义是实体完整性约束的一个主要方面。Key 表(密码信息表)
字段名称 数据类型 说明 K KeyName 文本 用户姓名 KeyNo 文本 用户密码 图4.18 密码信息表
密码信息表主要用于记录所有的用户名和用户密码。它是在用户登陆时用来确定用户和密码的正确性,以防止非法用户登陆。通过以上设计已经完成了系统的概要设计,当我们有了系统的功能模块图和数据库之后,就需要着手去实现每一个模块,为每一个功能设计程序流程图,这也就是系统的详细设计。§4.3 系统详细设计
在前面的概要设计中,已将系统划分为多个模块,并将它们按照一定的原则组装起来,同时确定了每个功能及模块之间的外部接口。现在所要做的就是确定每个模块具体执行过程,也可以说是“过程设计”。
在处理过程设计时我采用的是结构化程序设计(简称SP)方法。需要指出的是系统的详细设计并不是指具体的编程序,而是将概要设计阶段产生的系统功能模块图细化成很容易产生程序的图纸。因此详细设计的结果基本决定了最终程序的质量。为软件的质量,延长软件的生存期,软件的可测试性、可维护性提供重要的保障。详细设计的目标不仅是逻辑上正确地实现每个模块的功能,还应使设计出的处理过程清晰易读。
由前一阶段产生的系统功能模块图,我为系统的主要部分设计了如下程序流程图:通过以上步骤,基本上完成了对整个系统的总体设计,接下来所要做的就是软件的编码工作。系统总体设计的好坏直接影响着下一步工作,只有在这一阶段设计出好的模块图和程序流程图,才能更有利于编码,产生好的软件系统。
第五章
系统应用程序设计 §5.1 系统窗体模块组成 §5.2 数据模块窗体的设置
在编写数据库应用程序时,经常要遇到这样的情况,即好多组件、窗体同时访问相同的数据源,如果为每一个组件或者窗体都设置一个数据源将是十分耗时的工件,而且要保证这些数据源的确是相同的也需花一番功夫。那么,能不能将这些数据源集中管理,最好是做成一个统一的模块,需要时就将该模块引入而不必直接操作数据源本身呢?数据模块(DataModule)是解决这个问题最好的答案。简单说来,数据模块是用来集中管理数据源的一个窗体,该窗体可被需要的地方随时引入。
图5.2给出了本程序的数据模块(datamoduleform)窗体图,除报表窗体外所有的数据存取组件和数据源组件都在此数据模块中进行了定义。值得一提的是,设置了数据库Database组件,该组件引入了系统所需的唯一的数据库tsxs,Database组件的DatabaseName属性设置为tsckgl。tsxs数据库已在ODBC配置程序中进行了设置。其他的数据存取组件都是基于此数据库组件创建的,这样做的好处是,当数据库的别名或者其他信息改变之后,只需修改Tdatabase组件的AliasName属性即可。
另外,在本系统的数据模块窗体图中,我大多采用的AODQuery组件而没有采用BDE组,这主要是基于对ADO组件的了解。在Delphi的学习中我对ADO组件了解的更加清楚,使用也较BDE更为熟练,而且,ADO组件的功能也较BDE更为强大,所以在这里大多采用ADO组件来进行数据库联接。同时我也使用了BDE组件中的Table,因为在某些时候BDE有着其自身特有的优越性。主窗体功能模块的实现 file://主窗体程序代码
public
file://在程序的起始部分,定义快捷按钮点击事件 Procedure Popup1Handler(Sender:Tobject);Procedure Popup2Handler(Sender:TObject);********************************************************************** procedure Tmainform.Popup1Handler(Sender: TObject);begin file://快捷按钮1(点“按出版社分类”按钮产生)的点击事件 with datamoduleform.MainQuery do
begin
file://打开数据模块窗体的MainQuery,对BookRecord表进行操作 close;
file://关闭MainQuery SQL.Clear;
file://清除SQL属性中的SQL命令语句
SQL.Add(„select * from BookRecord where Publisher=:Pub„);file://添加新的SQL语句 Parameters.ParamByName(„Pub„).Value:=(Sender as TMenuItem).Caption;open;
file://重新打开MainQuery end;end;********************************************************************** procedure Tmainform.SpeedButton1Click(Sender: TObject);Var s1,s2,s3,s4,s5 :String;
file://设立5个变量以方便实现模糊查询 begin
file://主窗口库存查询按钮事件 with datamoduleform.MainQuery do begin close;SQL.Clear;SQL.Add(„select * from BookRecord„);
SQL.Add(„where BookID Like :BookID and BookName Like :Name and Author Like :Author and Publisher Like :pub and BookType Like :BookType„);
file://使用Like语句来实现模糊查询
if Edit1.Text<>„„ then s1:=„%„+Edit1.Text+„%„ else s1:=„%„;
Parameters.ParamByName(„BookID„).Value:=s1;
file://给变量s1赋值 if Edit2.Text<>„„ then s2:=„%„+Edit2.Text+„%„ else s2:=„%„;
Parameters.ParamByName(„Name„).Value:=s2;
file://给变量s2赋值 if Edit3.Text<>„„ then s3:=„%„+Edit3.Text+„%„ else s3:=„%„;
Parameters.ParamByName(„Author„).Value:=s3;
file://给变量s2赋值 if Edit4.Text<>„„ then s4:=„%„+Edit4.Text+„%„ else s4:=„%„;
Parameters.ParamByName(„Pub„).Value:=s4;
file://给变量s2赋值 if Edit5.Text <>„„ then s5:=„%„+Edit5.Text+„%„ else s5:=„%„;
Parameters.ParamByName(„BookType„).Value:=s5;
file://给变量s2赋值 open;if FieldValues[„BookID„]=NULL
file://判断是否找到记录 then begin Messagedlg(„没有找到你所需要的记录!„,mtInformation,[mbOK],0);Edit1.Text:=„„;Edit2.Text:=„„;Edit3.Text:=„„;Edit4.Text:=„„;Edit5.Text:=„„;close;SQL.Clear;SQL.Add(„select * from BookRecord„);
file://这里相当于一个刷新功能 open;end;end;end;********************************************************************** procedure Tmainform.SpeedButton3Click(Sender: TObject);begin
file://库存表刷新按钮事件 with datamoduleform.MainQuery do begin close;SQL.Clear;SQL.Add(„select * from BookRecord„);open;end;end;********************************************************************** procedure Tmainform.SpeedButton11Click(Sender: TObject);var PopupItem:TMenuItem;begin
file://自动生成快捷按钮1的内容 with datamoduleform.BookQuery do begin
file://从数据库中选择出版社类型 close;SQL.Clear;SQL.Add(„select distinct Publisher from BookRecord„);open;PopupMenu1:=TPopupMenu.Create(Self);file://自动生成快捷菜单 PopupMenu1.AutoHotkeys:=maManual;file://自定义热键 while Not Eof do begin
file://根据出版社内容生成菜单子项 PopupItem:=TMenuItem.Create(Self);PopupItem.Caption:=FieldByName(„Publisher„).AsString;PopupMenu1.Items.Add(PopupItem);PopupItem.onClick:=Popup1Handler;
file://确定菜单子项的点击事件 Next;end;end;PopupMenu1.Popup(384,67);
file://在指定位置显示快捷菜单1 end;********************************************************************** procedure Tmainform.FormActivate(Sender: TObject);begin
file://系统初始化,在进入mainform时自动添加数据源 mainform.DBGrid1.DataSource:=datamoduleform.MainSource;mainform.DBNavigator1.DataSource:=datamoduleform.MainSource;mainform.DBGrid2.DataSource:=datamoduleform.EmpSource;mainform.DBNavigator2.DataSource:=datamoduleform.EmpSource;mainform.DBGrid3.DataSource:=datamoduleform.ShopSource;mainform.DBNavigator3.DataSource:=datamoduleform.ShopSource;mainform.DBGrid4.DataSource:=datamoduleform.InSource;mainform.DBNavigator4.DataSource:=datamoduleform.InSource;mainform.DBGrid5.DataSource:=datamoduleform.OutSource;mainform.DBNavigator5.DataSource:=datamoduleform.OutSource;end;********************************************************************** procedure Tmainform.FormCreate(Sender: TObject);begin
file://系统初始化,定义界面大小,以适应不同分辩率 Width:=800;Height:=600;end;********************************************************************** procedure Tmainform.Timer1Timer(Sender: TObject);begin
file://在状态栏显示时间
StatusBar1.Panels[2].Text:=DateToStr(Date);StatusBar1.Panels[4].Text:=TimeToStr(Time);end;§5.4 入库、出库窗体模块的实现
图5.4 系统入库管理窗体
图5.5 系统出库管理窗体
procedure Tinoutform.SpeedButton4Click(Sender: TObject);begin
file://入库管理查找按钮事件
with datamoduleform.BookQuery do file://入库查询处理
begin
close;
SQL.Clear;
SQL.Add(„select * from BookRecord where BookID=:BookID„);
Parameters.ParamByName(„BookID„).Value:=Edit13.Text;
open;
if FieldValues[„BookID„]<>NULL then begin
Edit1.Text:=„„;
Edit1.ReadOnly:=true;Edit1.Color:=clMenu;
Edit6.Text:=FieldValues[„BookName„];file://显示图书名
Edit6.ReadOnly:=true;Edit6.Color:=clMenu;file://设置显示框不可更改属性
Edit7.Text:=FieldValues[„Author„];
Edit7.ReadOnly:=true;Edit7.Color:=clMenu;
Edit8.Text:=FieldValues[„Publisher„];
Edit8.ReadOnly:=true;Edit8.Color:=clMenu;
Edit9.Text:=FieldValues[„PubDate„];
Edit9.ReadOnly:=true;Edit9.Color:=clMenu;
Edit10.Text:=FieldValues[„Price„];
Edit10.ReadOnly:=true;Edit10.Color:=clMenu;
Edit11.Text:=FieldValues[„BookType„];
Edit11.ReadOnly:=true;Edit11.Color:=clMenu;
Edit12.Text:=FieldValues[„Number1„];
Edit12.ReadOnly:=true;Edit12.Color:=clMenu;
If FieldValues[„Addation„]<>NULL then Edit25.Text:=FieldValues[„Addation„]
else Edit25.Text:=„„;
Edit25.ReadOnly:=true;Edit25.Color:=clMenu;
end
else
begin file://在没有查找到的情况下,清空所有显示框
Edit1.ReadOnly:=false;Edit1.Text:=„„;Edit1.Color:=clMenu;
Edit6.ReadOnly:=false;Edit6.Text:=„„;Edit6.Color:=clMenu;
Edit7.ReadOnly:=false;Edit7.Text:=„„;Edit7.Color:=clMenu;
Edit8.ReadOnly:=false;Edit8.Text:=„„;Edit8.Color:=clMenu;
Edit9.ReadOnly:=false;Edit9.Text:=„„;Edit9.Color:=clMenu;
Edit10.ReadOnly:=false;Edit10.Text:=„„;Edit10.Color:=clMenu;
Edit11.ReadOnly:=false;Edit11.Text:=„„;Edit11.Color:=clMenu;
Edit12.ReadOnly:=false;Edit12.Text:=„„;Edit12.Color:=clMenu;
Edit25.ReadOnly:=false;Edit25.Text:=„„;Edit25.Color:=clMenu;
MessageDlg(„没有找到你所需要的记录!„,mtInformation,[mbOK],0);
Edit13.Text:=„„;Edit13.SetFocus;
end;end;with datamoduleform.InQuery do file://自动入库编号的获取
begin
close;
SQL.Clear;
SQL.Add(„select * from InRecord where InID>=All(select InID from InRecord)„);
open;
file://找到入库编号中最大的一个
Edit26.ReadOnly:=false;
Edit26.Text:=FieldValues[„InID„]+1;file://最大的入库编号加1形成新的入库编号
Edit26.ReadOnly:=true;Edit26.Color:=clMenu;file://设置编号的不可更改性
end;end;********************************************************************** procedure Tinoutform.SpeedButton1Click(Sender: TObject);var s:integer;begin file://入库管理添加按钮事件
if Edit1.Text<>NULL then MessageDlg(„请输入完整的入库信息和图书信息,然后单击确定按钮。„, mtInformation,[mbok],0)else begin
if(Edit2.Text=„„)or(Edit3.Text=„„)or(Edit4.Text=„„)or(Edit5.Text=„„)
then begin
MessageDlg(„请输入完整的入库信息!„,mtInformation,[mbok],0);
Edit2.SetFocus;
end
else begin
with datamoduleform.InQuery do file://将找到的图书信息显示
begin
close;
SQL.Clear;SQL.Add(„insert into InRecord values(:InID,:BookID,:EmpID,:ShopID, :Number,:InDate)„);file://向入库信息表中插入记录
Parameters.ParamByName(„InID„).Value:=Edit26.Text;file://向Edit框取值
Parameters.ParamByName(„BookID„).Value:=Edit13.Text;
Parameters.ParamByName(„EmpID„).Value:=Edit2.Text;
Parameters.ParamByName(„ShopID„).Value:=Edit3.Text;
Parameters.ParamByName(„Number„).Value:=Edit4.Text;
Parameters.ParamByName(„InDate„).Value:=Edit5.Text;
execSQL;
end;
Edit12.ReadOnly:=False;
S:=StrToInt(Edit12.Text)+StrToInt(Edit4.Text);file://计算入库后库存图书数量
Edit12.Text:=IntToStr(s);file://将修改后的库存图书数量显示
Edit12.ReadOnly:=true;
with datamoduleform.BookQuery do
file://修改库存记录中图书数量
begin
close;
SQL.Clear;
SQL.Add(„update BookRecord set Number1=:Number where BookID=:BookID„);
Parameters.ParamByName(„Number„).Value:=s;
Parameters.ParamByName(„BookID„).Value:=Edit13.Text;
execSQL;
file://提交SQL语句
MessageDlg(„记录已成功添加!„,mtInformation,[mbOK],0);
Edit13.SetFocus;
end;
end;end;end;********************************************************************** procedure Tinoutform.SpeedButton2Click(Sender: TObject);begin
file://入库管理确定按钮事件
if(Edit2.Text=„„)or(Edit3.Text=„„)or(Edit4.Text=„„)or(Edit5.Text=„„)
or(Edit6.Text=„„)or(Edit7.Text=„„)or(Edit8.Text=„„)or(Edit9.Text=„„)
or(Edit10.Text=„„)or(Edit11.Text=„„)or(Edit25.Text=„„)
then begin file://判断输入信息的完整性
MessageDlg(„请输入所需的全部入库信息!„,mtInformation,[mbok],0);Edit2.SetFocus;end else begin
with datamoduleform.InQuery do file://入库信息添加
begin
close;
SQL.Clear;SQL.Add(„insert into InRecord values(:InID,:BookID,:EmpID,:ShopID, :Number,:InDate)„);
file://向入库信息表中插入记录
Parameters.ParamByName(„InID„).Value:=Edit26.Text;
Parameters.ParamByName(„BookID„).Value:=Edit1.Text;
Parameters.ParamByName(„EmpID„).Value:=Edit2.Text;
Parameters.ParamByName(„ShopID„).Value:=Edit3.Text;
Parameters.ParamByName(„Number„).Value:=Edit4.Text;
Parameters.ParamByName(„InDate„).Value:=Edit5.Text;
execSQL;
end;
with datamoduleform.BookQuery do
begin
close;
SQL.Clear;
file://在完成入库信息的添加后,修改库存记录 SQL.Add(„insert into BookRecord values(:BookID,:BookName,:Author, :Publisher,:PubDate,:Price,:BookType,:Number,:Addration)„);
Parameters.ParamByName(„BookID„).Value:=Edit1.Text;
Parameters.ParamByName(„BookName„).Value:=Edit6.Text;
Parameters.ParamByName(„Author„).Value:=Edit7.Text;
Parameters.ParamByName(„Publisher„).Value:=Edit8.Text;
Parameters.ParamByName(„PubDate„).Value:=Edit9.Text;
Parameters.ParamByName(„Price„).Value:=Edit10.Text;
Parameters.ParamByName(„BookType„).Value:=Edit11.Text;
Parameters.ParamByName(„Number„).Value:=Edit4.Text;
Parameters.ParamByName(„Addration„).Value:=Edit25.Text;
execSQL;
end;
MessageDlg(„记录添加成功!„,mtInformation,[mbok],0);
end;end;********************************************************************** procedure Tinoutform.SpeedButton11Click(Sender: TObject);begin file://新书入库按钮事件
Edit13.Text:=„„;Edit13.Color:=clMenu;with datamoduleform.InQuery do file://自动入库编号的获取
begin close;SQL.Clear;SQL.Add(„select * from InRecord where InID>=All(select InID from InRecord)„);
open;Edit26.Text:=FieldValues[„InID„]+1;
Edit26.ReadOnly:=true;Edit26.Color:=clMenu;end;with datamoduleform.BookQuery do file://自动图书编号的获取
begin close;
SQL.Clear;
SQL.Add(„select * from BookRecord where BookID>=All(select BookRecord)„);
file://找到库存图书编号中最大的一个
open;
Edit1.ReadOnly:=false;
Edit1.Text:=FieldValues[„BookID„]+1;file://显示自动生成的图书编号
Edit1.ReadOnly:=true;Edit1.Color:=clMenu;end;Edit2.Text:=„„;Edit3.Text:=„„;Edit4.Text:=„„;Edit5.Text:=„„;
Edit6.ReadOnly:=false;Edit6.Text:=„„;Edit6.Color:=clWindow;
Edit7.ReadOnly:=false;Edit7.Text:=„„;Edit7.Color:=clWindow;
Edit8.ReadOnly:=false;Edit8.Text:=„„;Edit8.Color:=clWindow;
Edit9.ReadOnly:=false;Edit9.Text:=„„;Edit9.Color:=clWindow;
Edit10.ReadOnly:=false;Edit10.Text:=„„;Edit10.Color:=clWindow;
Edit11.ReadOnly:=false;Edit11.Text:=„„;Edit11.Color:=clWindow;
Edit12.ReadOnly:=false;Edit12.Text:=„„;Edit12.Color:=clMenu;
Edit25.ReadOnly:=false;Edit25.Text:=„„;Edit25.Color:=clWindow;end;procedure Tinoutform.SpeedButton22Click(Sender: TObject);var s:integer;begin file://出库管理确定按钮事件
if(Edit24.Text=„„)or(Edit27.Text=„„)or(Edit28.Text=„„)then begin MessageDlg(„请输入完整的出库信息!„,mtInformation,[mbok],0);Edit24.SetFocus;end else begin if Edit27.Text>Edit21.Text file://检查出库数量是否小于库存数量 then begin MessageDlg(„库存中的图书数量不够!„,mtInformation,[mbok],0);Edit27.Text:=„„;Edit27.SetFocus;
end else begin with datamoduleform.OutQuery do begin
BookID from close;SQL.Clear;SQL.Add(„insert into OutRecord values(:OutID,:BookID,:EmpID, :Number,:OutTime)„);file://添加出库记录
Parameters.ParamByName(„OutID„).Value:=Edit23.Text;Parameters.ParamByName(„BookID„).Value:=Edit14.Text;Parameters.ParamByName(„EmpID„).Value:=Edit24.Text;Parameters.ParamByName(„Number„).Value:=Edit27.Text;Parameters.ParamByName(„OutTime„).Value:=Edit28.Text;execSQL;end;Edit21.ReadOnly:=False;s:=StrToInt(Edit21.Text)-StrToInt(Edit27.Text);file://计算出库后库存图书数量 Edit21.Text:=IntToStr(s);file://显示出库后库存图书数量 Edit21.ReadOnly:=True;with datamoduleform.BookQuery do begin
file://修改库存图书数量 close;SQL.Clear;SQL.Add(„update BookRecord set Number1=:Number where BookID=:BookID„);Parameters.ParamByName(„Number„).Value:=s;
Parameters.ParamByName(„BookID„).Value:=Edit14.Text;execSQL;end;MessageDlg(„出库记录添加成功!„,mtInformation,[mbok],0);Edit14.Text:=„„;Edit14.SetFocus;end;end;end;
§5.5 查询功能的实现
查询功能包括员工信息查询,供应商信息查询,入库信息查询和出库信息查询。由于每一个功能的实现都差不太多,而且其窗体也差不太多,所以在这里只给出员工信息查询窗体及其源代码。
图5.6 员工信息查询窗体
procedure Tfindempform.SpeedButton1Click(Sender: TObject);Var s1,s2,s3 :String;begin
file://员工记录查询窗体查找按钮事件 with datamoduleform.EmpQuery do begin close;SQL.Clear;SQL.Add(„select * from Employee„);
SQL.Add(„where EmployeeID Like :EmpID and EmployeeName Like :Name and Grade Like :Grade„);
file://实现模糊查询功能
if Edit1.Text<>„„ then s1:=„%„+Edit1.Text+„%„ else s1:=„%„;Parameters.ParamByName(„EmpID„).Value:=s1;
if Edit2.Text<>„„ then s2:=„%„+Edit2.Text+„%„ else s2:=„%„;Parameters.ParamByName(„Name„).Value:=s2;
if Edit3.Text<>„„ then s3:=„%„+Edit3.Text+„%„ else s3:=„%„;Parameters.ParamByName(„Grade„).Value:=s3;open;if FieldValues[„EmployeeID„]<>NULL
then findempform.Close
file://在找到记录的情况下关闭查找窗口 else begin MessageDlg(„没有找到你所需要的记录!„,mtInformation,[mbOK],0);Edit1.Text:=„„;Edit2.Text:=„„;Edit3.Text:=„„;Edit1.SetFocus;close;SQL.Clear;SQL.Add(„select * from Employee„);file://刷新员工信息窗口 open;end;end;end;§5.6 系统登陆窗体模块的实现
由于系统登陆窗体中有一幅彩图,在这里不便给出,而只给出了系统的实现。var keyname: string;file://定义了一个全局变量,在key2中有调用 procedure Tkeyform.SpeedButton1Click(Sender: TObject);var s:string;
file://登陆窗口登陆按钮事件 begin if(Edit1.Text=„„)then begin MessageDlg(„清输入登陆姓名和密码!„,mtInformation,[mbok],0);Edit1.SetFocus;end else begin datamoduleform.KeyTable.Active:=true;if not datamoduleform.KeyTable.Locate(„KeyName„,Edit1.Text,[])
file://判断登陆名是否存在 then begin MessageDlg(„登陆名错误,请重新输入!„,mtInformation,[mbok],0);Edit1.Text:=„„;Edit1.SetFocus;end else begin with datamoduleform.KeyQuery do begin close;SQL.Clear;SQL.Add(„select * from Key where KeyName=:KeyName„);Parameters.ParamByName(„KeyName„).Value:=Edit1.Text;open;s:=FieldValues[„KeyNo„];end;if s<>Edit2.Text file://判断登陆密码是否正确 then begin MessageDlg(„登陆密码错误,请重新输入!„,mtInformation,[mbok],0);Edit2.Text:=„„;Edit2.SetFocus;end else begin keyname:=Edit1.Text;keyform.Hide;mainform.Show;mainform.WindowState:=wsMaximized;end;end;end;end;§5.7 用户管理功能的实现 5.7.1 用户管理主窗体
图5.7 用户管理主窗体 5.7.2 密码修改窗体模块的实现
图5.8 密码修改窗体
procedure Tkey2form.SpeedButton1Click(Sender: TObject);begin file://密码修改窗口修改按钮事件 if(Edit1.Text=„„)or(Edit2.Text=„„)or(Edit3.Text=„„)then begin MessageDlg(„请输入完整的信息。„,mtInformation,[mbok],0);Edit1.SetFocus;end else begin if Not datamoduleform.KeyTable.Locate(„KeyNo„,Edit1.Text,[])then begin MessageDlg(„原密码输入错误,不能修改新密码!„,mtInformation,[mbok],0);Edit1.Text:=„„;Edit2.Text:=„„;Edit3.Text:=„„;Edit1.SetFocus;end else begin if Edit2.Text<>Edit3.Text then begin MessageDlg(„两次密码输入不同,请重新输入新密码!„,mtInformation,[mbok],0);Edit2.Text:=„„;Edit3.Text:=„„;Edit2.SetFocus;end else begin
file://在数据库中修改密码 with datamoduleform.KeyQuery do begin close;SQL.Clear;SQL.Add(„update key set KeyNo=:KeyNo where KeyName=:KeyName„);Parameters.ParamByName(„KeyName„).Value:=keyname;Parameters.ParamByName(„KeyNo„).Value:=Edit2.Text;execSQL;MessageDlg(„密码修改成功!„,mtInformation,[mbok],0);key2form.Close;end;end;end;end;end;5.7.3 用户注册窗体模块的实现
图5.9 用户注册窗体
procedure Tkey3form.SpeedButton1Click(Sender: TObject);begin file://用户注删窗口注删按钮事件 if(Edit1.Text=„„)or(Edit2.Text=„„)or(Edit3.Text=„„)then begin MessageDlg(„请输入完整的信息!„,mtInformation,[mbok],0);Edit1.SetFocus;end else begin if datamoduleform.KeyTable.Locate(„KeyName„,Edit1.Text,[])
file://判断用户名是否存在,系统不允许用户名重复 then begin MessageDlg(„用户名已存在,请输入新的用户名和密码!„, mtInformation,[mbok],0);Edit1.Text:=„„;Edit2.Text:=„„;Edit3.Text:=„„;Edit1.SetFocus;end else begin if Edit2.Text<>Edit3.Text then begin MessageDlg(„您输入的两个密码不相同,请重新输入!„,mtInformation,[mbok],0);Edit2.Text:=„„;Edit3.Text:=„„;Edit2.SetFocus;end else begin with datamoduleform.KeyQuery do
file://在数据库中添加该用户 begin close;SQL.Clear;SQL.Add(„insert into Key values(:KeyName,:KeyNo)„);Parameters.ParamByName(„KeyName„).Value:=Edit1.Text;Parameters.ParamByName(„KeyNo„).Value:=Edit2.Text;execSQL;end;MessageDlg(„新用户添加成功,您可以继续添加用户,或按“取消”退出。„,mtInformation,[mbok],0);
Edit1.Text:=„„;Edit2.Text:=„„;Edit3.Text:=„„;Edit1.SetFocus;end;end;end;end;5.7.4 用户注销窗体模块的实现
图5.10 用户注销窗体
procedure Tkey4form.SpeedButton1Click(Sender: TObject);var s:string;begin file://用户注销窗口注销按钮事件 if(Edit1.Text=„„)or(Edit2.Text=„„)
then MessageDlg(„请输入完整的信息!„,mtInformation,[mbok],0)else begin if Not datamoduleform.KeyTable.Locate(„KeyName„,Edit1.Text,[])
file://判断用户名是否存在,用户名必须存在,才可以删除 then begin MessageDlg(„您所输入的用户名不存在,请重新输入或按“取消”退出。„, mtInformation,[mbok],0);Edit1.Text:=„„;Edit2.Text:=„„;Edit1.SetFocus;end else begin with datamoduleform.KeyQuery do begin close;SQL.Clear;SQL.Add(„select * from Key where KeyName=:KeyName„);Parameters.ParamByName(„KeyName„).Value:=Edit1.Text;open;s:=FieldValues[„KeyNo„];end;if s<>Edit2.Text file://判断该用户名下的密码是否正确 then begin MessageDlg(„您所输入的密码不正确,请重新输入或按“取消”退出。„, mtInformation,[mbok],0);Edit2.Text:=„„;Edit2.SetFocus;end else begin
file://从数据库中删除该用户 with datamoduleform.KeyQuery do begin close;SQL.Clear;SQL.Add(„delete from Key where KeyName=:KeyName„);Parameters.ParamByName(„KeyName„).Value:=Edit1.Text;execSQL;end;MessageDlg(„用户已成功删除,您可以继续删除用户,或按“取消”退出。„, mtInformation,[mbok],0);Edit1.Text:=„„;Edit2.Text:=„„;Edit1.SetFocus;end;end;end;end;
结束语
本系统是一个面向小型图书企业,具有一定实用性的数据库信息管理系统。它主要完成对图书仓库的一系列管理,包括入库、出库、库存以及员工和供应商信息管理。本系统采用当前流行的面向对象的开发工具—Delphi来完成整个系统的设计,在数据库的设计上利用了Access的便利性和实用性。
本系统具有相当的实用功能。在查询方面,系统实现了多条件任意字段的模糊查询,同时在分类查询上实现了动态生成,系统可以自动识别用户不同的输入。在图书入库、出库和库存三者之间建立了良好的链接关系,某一部分地修改均会自动引发系统对与其相关的部分进行连锁修改。在用户管理方面,系统较好地实现了用户注册,用户注销和密码修改等各项功能。系统在设计过程中不可避免地遇到了各种各样的问题,由于整个系统完全都是由个人设计的,有关Delphi许多细节问题都要靠自己去摸索,加之本人水平有限,并没有完全地理解Delphi的强大功能,而且还存在着许多不足之处。如:
※
受开发条件和开发时间的限制,本系统只利用了本地数据库Access,它同应用程序处于同一系统中,能存储的数据量也有一定限制,并没有发挥出Delphi其数据库方面的优势; ※
报表打印功能尚不够全面完善,不能实现动态报表;
※
在一些数据输入时没有及时的进行数据格式校验,不能保证数据输入的绝对正确性。※
由于时间关系,系统功能实现不够完善,使用不是很方便,比如,没有实现多条记录的连锁删除和添加以及数据的导入功能。这些都是需要完善的地方,该系统离实际使用也还有相当的距离,需要我进行不断地补充和完善。
通过本次毕业设计我学到了不少新的东西,也发现了大量的问题,有些在设计过程中已经解决,有些还有待今后慢慢学习。只要学习就会有更多的问题,有更多的难点,但也会有更多的收获。
考 文 献
[1] 郑荣贵、黄平、谷会东,Delphi 6.0数据库开发与应用,中科多媒体电子出版社,2002 [2] 伍俊良,Delphi 6控件应用实例教程,北京希望电子出版社,2002 [3] 卢国俊,Delphi 6数据库开发,电子工业出版社,2002 [4] 边萌,Delphi 编程起步,机械工业出版社,2002 [5] 伍俊良,Delphi 6课程设计案例精编,中国水利水电出版社,2002 [6] 丁宝康,数据库原理,经济科学出版社,2000 [7] 陆丽娜,软件工程,经济科学出版社,2000
第三篇:Delphi图书仓库管理系统论文
Delphi图书仓库管理系统论文Delphi图书仓库管理系统论文
前 言
随着社会经济的迅速发展和科学技术的全面进步,计算机事业的飞速发展,以计算机与通信技术为基础的信息系统正处于蓬勃发展的时期.随着经济文化水平的显著提高,人们对生活质量及工作环境的要求也越来越高.书籍做为人类的精神食粮,在现代社会中越来越受到重视,大量的书籍出现在市场上,人们有了各种各样不同的选择.与此同时,为了管理大量的图书,图书仓库也大量的出现,仓库的管理问题也就提上了日程.随着图书的大量增加,其管理难度也越来越大,如何优化仓库的日常管理也就成为了一个大众化的课题.在计算机飞速发展的今天,将计算机这一信息处理利器应用于仓库的日常管理已是势必所然,而且这也将为仓库管理带来前所未有的改变,它可以带来意想不到的效益,同时也会为企业的飞速发展提供无限潜力.采用计算机管理信息系统已成为仓库管理科学化和现代化的重要标志,它给企业管理来了明显的经济效益和社会效益.主要体现在:
极大提高了仓库工作人员的工作效率,大大减少了以往入出存流程繁琐,杂乱,周期长的弊端.基于仓库管理的全面自动化,可以减少入库管理,出库管理及库存管理中的漏洞,可以节约不少管理开支,增加企业收入.仓库的管理的操作自动化和信息的电子化,全面提高了仓库的管理水平.随着我国改革开放的不断深入,经济飞速的发展,企业要想生存,发展,要想在激烈的市场竞争中立于不败之地,没有现代化的管理是万万不行的,仓库管理的全面自动化,信息化则是其中极其重要的部分.为了加快仓库管理自动化的步伐,提高仓库的管理业务处理效率,建立仓库管理系统已变得十分心要.入库,库存,出库还是现在企业图书仓库管理的常规基本模式,虽然,最近又出现了很多新的管理模式,如:基于零库存思想的沃尔玛特管理方式,但这些新的思想在中国大部分企业的管理中还是难以实现的.所以如何设计好仓库管理系统,尽可能地减少仓库管理的重复性和低效性就成为当前最为重要的问题.图书仓库管理的核心是入库,库存和出库之间的联系,如何处理好三者之间的关系是系统最为关键的部分.另外,员工信息和供应商信息管理也是仓库管理中一个必不可少的部分,它提供着与入库和出库相关的一些信息,使得整个系统更加完整,更加实用.通过对仓库管理日常工作的详细调查,搜集了大量的资料,从系统结构的组织,功能的实现,技术的要求以及可行性等多方面进行考虑,认为本课题是一个适应现今图书仓库管理需求的计算机信息管理系统,具有一定的实际开发价值和使用价值.内 容 简 介
本系统主要完成对图书仓库的库存管理,包括图书入库,出库,库存,员工信息,供应商信息以及密码管理等六个方面.系统可以完成对各类信息的浏览,查询,添加,删除,修改,报表等功能.系统的核心是入库,库存和出库三者之间的联系,每一个表的修改都将联动的影响其它的表,当完成入库或出库操作时系统会自动地完成库存的修改.查询功能也是系统的核心之一,在系统中即有单条件查询和多条件查询,也有精确查询和模糊查询,系统不仅有静态的条件查询,也有动态生成的条件查询,其目的都是为了方便用户使用.系统有完整的用户添加,删除和密码修改功能,并具备报表打印功能.系统采用MICROSOFT OFFICE中的ACCESS 2000来设计数据库,并使用当前优秀的开发工具—DELPHI 6.0 ,它有着最为灵活的数据库结构,对数据库应用有着良好的支持.论文主要介绍了本课题的开发背景,所要完成的功能和开发的过程.重点的说明了系统设计的重点,设计思想,难点技术和解决方案.具体安排如下:
第一章进行系统的需求分析.第二章介绍系统的概要设计.第三章介绍了系统详细设计.第四章介绍了程序设计环境及选用的语言工具.第五章根据前四章的设计结果利用ACCESS 2000和DELPHI 6.0进行了具体的窗体和应用程序设计.总结部分介绍了设计体会和编程体会,并指出了系统设计中的不足和改进的方向.关键字:图书仓库管理,数据库,DELPHI,SQL,ACCESS.
第四篇:图书仓库管理系统(doc 61)
管理资源吧(www.xiexiebang.com),海量企业管理资料免费下载!
图书仓库管理系统
摘 要
本系统主要完成对图书仓库的库存管理,包括图书入库、出库、库存,员工信息,供应商信息以及密码管理等六个方面。系统可以完成对各类信息的浏览、查询、添加、删除、修改、报表等功能。
系统的核心是入库、库存和出库三者之间的联系,每一个表的修改都将联动的影响其它的表,当完成入库或出库操作时系统会自动地完成库存的修改。查询功能也是系统的核心之一,在系统中即有单条件查询和多条件查询,也有精确查询和模糊查询,系统不仅有静态的条件查询,也有动态生成的条件查询,其目的都是为了方便用户使用。系统有完整的用户添加、删除和密码修改功能,并具备报表打印功能。
系统采用Microsoft Office中的Access 2000来设计数据库,并使用当前优秀的开发工具—Delphi 6.0,它有着最为灵活的数据库结构,对数据库应用有着良好的支持。
论文主要介绍了本课题的开发背景,所要完成的功能和开发的过程。重点的说明了系统设计的重点、设计思想、难点技术和解决方案。
关键字:数据库,SQL语言,Delph 6,数据库组件,仓库管理
目 录
更多免费下载,敬请登陆:www.xiexiebang.com 第一章 引言 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„1 1.1 课题来源 „„„„„„„„„„„„„„„„„„„„„„„„„„1 1.2 开发工具的选择 „„„„„„„„„„„„„„„„„„„„„„„2 1.3 所做的主要工作 „„„„„„„„„„„„„„„„„„„„„„„3 第二章 数据库概论 „„„„„„„„„„„„„„„„„„„„„„„„„„4
2.1 数据库的发展 „„„„„„„„„„„„„„„„„„„„„„„„4 2.1.1 数据库的发展 „„„„„„„„„„„„„„„„„„„„„„4 2.1.2 数据库阶段的特点 „„„„„„„„„„„„„„„„„„„„5 2.1.3 数据库技术 „„„„„„„„„„„„„„„„„„„„„„„6 2.2 数据库理论基础 „„„„„„„„„„„„„„„„„„„„„„„7 2.2.1 数据库模型 „„„„„„„„„„„„„„„„„„„„„„„7 2.2.2 数据库体系结构 „„„„„„„„„„„„„„„„„„„„10
2.2.3 数据的独立性 „„„„„„„„„„„„„„„„„„„„„11 2.2.4 范式 „„„„„„„„„„„„„„„„„„„„„„„„„11 2.3 SQL语言基础 „„„„„„„„„„„„„„„„„„„„„„„13 2.3.1 SQL简介 „„„„„„„„„„„„„„„„„„„„„„„13 2.3.2 SQL查询 „„„„„„„„„„„„„„„„„„„„„„„13 2.3.3 SQL数据更新 „„„„„„„„„„„„„„„„„„„„„14 第三章数据库开发工具 „„„„„„„„„„„„„„„„„„„„„„„16 3.1 Delphi 6.0 简介 „„„„„„„„„„„„„„„„„„„„„„„16
3.2 Delphi 6.0 控件 „„„„„„„„„„„„„„„„„„„„„„„17 3.2.1 ADO数据访问组件 „„„„„„„„„„„„„„„„„„„17 3.2.2 数据控制类DataControl „„„„„„„„„„„„„„„„„18 3.2.3 数据访问类DataAccess „„„„„„„„„„„„„„„„„18 3.2.4 SQL语言在Delphi中的应用 „„„„„„„„„„„„„„„19 3.3 Access 简介 „„„„„„„„„„„„„„„„„„„„„„„„21 第四章 系统总体设计 „„„„„„„„„„„„„„„„„„„„„„„„23
4.1 系统需求分析 „„„„„„„„„„„„„„„„„„„„„„„23 4.2 系统概要设计 „„„„„„„„„„„„„„„„„„„„„„„25 4.2.1 系统结构设计 „„„„„„„„„„„„„„„„„„„„„25 4.2.2 数据库设计 „„„„„„„„„„„„„„„„„„„„„„27
4.2.2.1 ER图设计 „„„„„„„„„„„„„„„„„„„„27 4.2.2.2 数据库表格设计„„„„„„„„„„„„„„„„„„29 4.3系统详细设计„„„„„„„„„„„„„„„„„„„„„„„„34 第五章 系统应用程序设计 „„„„„„„„„„„„„„„„„„„„„„37
5.1 系统窗体模块组成„„„„„„„„„„„„„„„„„„„„„„37 5.2 数据模块窗体设置„„„„„„„„„„„„„„„„„„„„„„38 5.3 主窗体功能模块的实现„„„„„„„„„„„„„„„„„„„„39 5.4 入库、出库窗体模块的实现„„„„„„„„„„„„„„„„„„43 5.5 查询功能的实现„„„„„„„„„„„„„„„„„„„„„„„51 5.6 系统登陆窗体模块的实现„„„„„„„„„„„„„„„„„„„52 5.7 用户管理功能的实现„„„„„„„„„„„„„„„„„„„„„54 5.7.1 用户管理主窗体 „„„„„„„„„„„„„„„„„„„„54 5.7.2 密码修改窗体模块的实现 „„„„„„„„„„„„„„„„54 5.7.3 用户注册窗体模块的实现 „„„„„„„„„„„„„„„„55 5.7.4 用户注销窗体模块的实现 „„„„„„„„„„„„„„„„57 结束语 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„59 致谢 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„60 参考文献 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„„61 第一章 引 言 §1.1 课题来源
随着社会经济的迅速发展和科学技术的全面进步,计算机事业的飞速发展,以计算机与通信技术为基础的信息系统正处于蓬勃发展的时期。随着经济文化水平的显著提高,人们对生活质量及工作环境的要求也越来越高。书籍做为人类的精神食粮,在现代社会中越来越受到重视,大量的书籍出现在市场上,人们有了各种各样不同的选择。与此同时,为了管理大量的图书,图书仓库也大量的出现,仓库的管理问题也就提上了日程。随着图书的大量增加,其管理难度也越来越大,如何优化仓库的日常管理也就成为了一个大众化的课题。
在计算机飞速发展的今天,将计算机这一信息处理利器应用于仓库的日常管理已是势必所然,而且这也将为仓库管理带来前所未有的改变,它可以带来意想不到的效益,同时也会为企业的飞速发展提供无限潜力。采用计算机管理信息系统已成为仓库管理科学化和现代化的重要标志,它给企业管理来了明显的经济效益和社会效益。主要体现在:
极大提高了仓库工作人员的工作效率,大大减少了以往入出存流程繁琐,杂乱,周期长的弊端。
基于仓库管理的全面自动化,可以减少入库管理、出库管理及库存管理中的漏洞,可以节约不少管理开支,增加企业收入。
仓库的管理的操作自动化和信息的电子化,全面提高了仓库的管理水平。随着我国改革开放的不断深入,经济飞速的发展,企业要想生存、发展,要想在激烈的市场竞争中立于不败之地,没有现代化的管理是万万不行的,仓库管理的全面自动化、信息化则是其中极其重要的部分。为了加快仓库管理自动化的步伐,提高仓库的管理业务处理效率,建立仓库管理系统已变得十分心要。入库、库存、出库还是现在企业图书仓库管理的常规基本模式,虽然,最近又出现了很多新的管理模式,如:基于零库存思想的沃尔玛特管理方式,但这些新的思想在中国大部分企业的管理中还是难以实现的。所以如何设计好仓库管理系统,尽可能地减少仓库管理的重复性和低效性就成为当前最为重要的问题。图书仓库管理的核心是入库、库存和出库之间的联系,如何处理好三者之间的关系是系统最为关键的部分。另外,员工信息和供应商信息管理也是仓库管理中一个必不可少的部分,它提供着与入库和出库相关的地一些信息,使得整个系统更加完整,更加实用。
通过对仓库管理日常工作的详细调查,搜集了大量的资料,从系统结构的组织,功能的实现,技术的要求以及可行性等多方面进行考虑,认为本课题是一个适应现今图书仓库管理需求的计算机信息管理系统,具有一定的实际开发价值和使用价值。
§1.2 开发工具的选择 自Java诞生以来,随着Internet技术的普及和应用需求的变化,以第四代语言为主的应用开发产品发生了较大的变化,它们不仅已成为人们开发应用的开发工具,而且很多产品已发展成为一种强有力的应用开发环境。这些新型的开发工具通常以一种集成软件包的形式提供给开发人员,被称为Studio(工作室)或Suite(程序组)。例如,微软的Visual Studio 6.0,Borland公司的Delphi 6.0等数据库辅助开发工具。
现在,市场上可以选购的应用开发产品很多,流行的也有数十种。目前在我国市场上最为流行、使用最多、最为先进的可用作企业级开发工具的产品有: Microsoft公司的Visual Basic 6.0版 Microsoft公司的Visual C++6.0版 Borland公司的Delphi 6.0版
在目前市场上这些众多的程序开发工具中,有些强调程语言的弹性与执行效率;有些则偏重于可视化程序开发工具所带来的便利性与效率的得高,各有各的优点和特色,也满足了不同用户的需求。然而,语言的弹性和工具的便利性是密不可分的,只有便利的工具,却没有弹性的语言作支持,许多特殊化的处理动作必需要耗费数倍的工夫来处理,使得原来所标榜的效率提高的优点失去了作用;相反,如果只强调程语言的弹性,却没有便利的工具作配合,会使一些即使非常简单的界面处理动作,也会严重地浪费程序设计师的宝贵时间。
而Delphi是一个非常理想选择。Delphi 6 是操作系统中快速应用开发环境的最新版本。它也是当前Windows平台上第一个全面支持最新Web服务的快速开发工具。无论是企业级用户,还是个人开发者,都能够利用Delphi 6 轻松、快捷地构建新一代电子商务应用。Delphi 6 是惟一支持所有新出现的工业标准的RAD环境,包括XML(扩展标记语言)/XSL(可扩展样式语言),SOAP(简单对象存取协议)和WSDL(Web服务器描述语言)等。
Delphi 6 是可视化的快速应用程序开发语言,它提供了可视化的集成开发环境,这一环境为应用程序设计人员提供了一系列灵活而先进的工具,可以广泛地用于种类应用程序设计。在Delphi 6 的集成开发环境中,用户可以设计程序代码、运行程序、进行程序错误的调试等,可视化的开发方法降低了应用程序开发的难度。Delphi的基础编程语言是具有面向对象特性的Pascal语言,即Object Pascal。Object Pascal具有代码稳定、可读性好、编译速度快等优点,并将面向对象的概念移植到了Pascal语言中,使这种基础语言有了新的发展空间。使用Delphi 6.0,我们几乎可以作任何事情,还可以撰写种各种类型的应用程序,动态链接库(DLL)、CON、或CORBA对象,CGI/ISAPI程序,Microsoft Back Office应用程序。程序的规模小到简单的个人数据库应用,大到复杂的企业的多层次分布式系统,都可以使用Delphi进行开发,其友好的集成开发界面,可视化的双向开发模式,良好的数据库应用支持高效的程序开发和程序运行,备受广大程序开发人员的好评。尤其是Delphi对数据库应用的强大支持,大大提高了数据库应用软件开发的效率,缩短了开发周期,深受广大数据库应用程序设计人员的喜爱。Delphi为数据库应用开发人员提供了丰富的数据库开发组件,使数据库应用开发功能更强大,控制更灵活,编译后的程序运行速度更快。§1.3 本文所做工作
引言部分介绍了本系统的课题来源以及对数据库开发工具的选择。
第二章介绍了数据库的发展,关系数据库,数据库体系结构,并系统介绍了SQL语言,为设计和理解应用程序做了铺垫。
第三章系统介绍了Delphi 6.0及其部分控件,SQL语言在Delphi 6.0中的应用,以及Access等。
第四章是本文的主体,按照软件工程的要求,从需求分析开始,经过概要设计最后到详细设计,完成对整个系统的设计。
第五章根据第四章的设计结果利用Access 2000和Delphi 6.0进行了具体的窗体和应用程序设计。
总结部分介绍了设计体会和编程体会,并指出了系统设计中的不足和改进的方向 第二章 数据库概论 §2.1 数据库的发展
数据库处理在信息系统的研究中一直是非常重要的主题,然而,近年来,随着World Wide Web(www.xiexiebang.com公司的TOTAL等
(3)关系模型。关系模型的主要是用二维表格结构表达实体集,用外键表示实体间联系。关系模型是由若干个关系模式组成的集合。关系模式相当于前面提到的记录类型,它的实例称为关系,每个关系实际上是一张二维表格。
关系模型和层次、网状模型的最大判别是用关键码而不是用指针导航数据,表格简单用户易懂,编程时并不涉及存储结构,访问技术等细节。关系模型是数学化模型。SQL语言是关系数据库的标准化语言,已得到了广泛的应用。20世纪70年代对关系数据库的研究主要集中在理论和实验系统的开发方面。80年代初才形成产品,但很快得到广泛的应用和普及,并最终取代了层次、网状数据库产品。现在市场上典型的关系DBMS产品有DB2、ORACLE、SYBASE、INFORMIX和微机型产品Foxpro、Access等。
关系模型和网状、层次模型的最大区别是:关系模型用表格数据而不是通过指针链来表示和实现实体间联系。关系模型的数据结构简单、易懂。只需用简单的查询语句就可对数据库进行操作。
关系模型是数学化的模型,可把表格看成一个集合,因此集合论、数理逻辑等知识可引入到关系模型中来。关系模型已是一个成熟的有前途的模型,已得到广泛应用。
(4)面向对象模型。目前,关系数据库的使用已相当普遍,但是,现实世界中仍然存在着许多含有复杂数据结构的应用领域,例如,CAD数据、图形数据等,而关系模型在这方面的处理能力就显得力不从心。因此,人们需要更高级的数据库技术来表达这类信息。面向对象的概念最早出现在程序设计语言中,随后迅速渗透到计算机领域的每一个分支。面向对象数据库是面向对象概念与数据库技术相结合的产物。
面向对象模型能完整地描述现实世界的数据结构,具有丰富的表达能力,但模型相对较复杂,涉及的知识面也广,因此面向对象数据库尚未达到关系数据库那样的普及程度。
2.2.2 数据库体系结构
数据库的体系结构分三级:内部级(internal),概念级(conceptual)和外部级(external)。这个三级结构有时也称为“三级模式结构”,或“数据抽象的三个级别”,最早是在1971年通过的DBTG报告中提出,后来收入在1975年的美国ANSI/SPARC报告中。虽然现在DBMS的产品多种多样,在不同的操作系统支持下工作,但是大多数系统在总的体系结构上都具有三级模式的结构特征。从某个角度看到的数据特性称为“数据视图”(data view)。外部级最接近用户,是单个用户所能看到的数据特性。单个用户使用的数据视图的描述称为“外模式”。
概念级涉及到所有用户的数据定义,是全局的数据视图。全局数据视图的描述称为“概念模式”。
内部级最接近于物理存储设备,涉及到实际数据存储的结构。物理存储数据视图的描述称为“内模式”。
数据库的三级模式结构是数据的三个抽象级别。它把数据的具体组织留给DBMS去做,用户只要抽象地处理数据,而不必关心数据在计算机中的表示和存储,这样就减轻了用户使用系统的负担。
三级结构之间往往差别很大,为了实现这三个抽象级别的联系和转换,DBMS在三级结构之间提供两个层次的映象(mappings):外模式/模式映象,模式/内模式映象。此处模式是概念模式的简称。2.2.3 数据的独立性
由于数据库系统采用三级模式结构,因此系统具有数据独立性的特点。在数据库技术中,数据独立性是指应用程序和数据之间相互独立,不受影响。数据独立性分成物理数据独立性和逻辑数据独立性两级。(1)物理数据独立性
如果数据库的内模式要进行修改,即数据库的存储设备和存储方法有所变化,那么模式/内模式映象也要进行相当的修改,使概念模式尽可能保持不变。也就是对内模式的修改尽量不影响概念模式,当然,对于外模式和应用程序的影响更小,这样,我们称数据库达到了物理数据独立性。(2)逻辑数据独立性
如果数据库的概念模式要进行修改,譬如增加记录类型或增加数据项,那么外模式/模式映象也要进行相应的修改,使外模式尽可能保持不变。也就是对概念模式的修改尽量不影响外模式和应用程序,这样,我们称数据库达到了逻辑数据独立性。现有关系系统产品均提供了较高的物理独立性,而对逻辑独立性的支持尚有欠缺,例如,对外模式的数据更新受到限制等。2.2.4 范式
建立起一个良好的数据指标体系,是建立数据结构和数据库的最重要的一环。一个良好的数据指标体系是建立DB的必要条件,但不是充分条件。我们完全可以认为所建指标体系中的一个指标类就是关系数据库中的一个基本表,而这个指标类下面的一个个具体指标就是这个基本表中的一个字段。但如果直接按照这种方式建库显然还不能算最佳。对于指标体系中数据的结构在建库前还必须进行规范化的重新组织。
在数据的规范化表达中,一般将一组相互关联的数据称为一个关系(relation),而在这个关系下的每个数据指标项则被称为数据元素(data element),这种关系落实到具体数据库上就是基本表,而数据元素就是基本表中的一个字段(field)。规范化表达还规定在每一个基本表中必须定义一个数据元素为关键字(key),它可以唯一地标识出该表中其它相关的数据元素。在规范化理论中表是二维的,它有如下四个性质:
在表中的任意一列上,数据项应属于同一个属性(如图中每一列都存放着不同合同记录的同一属性数据)。
表中所有行都是不相同的,不允许有重复组项出现(如图中每一行都是一个不同的合同记录)。
在表中,行的顺序无关紧要(如图中每行存的都是合同记录,至于先放哪一个合同都没关系)。
在表中,列的顺序无关紧要,但不能重复(如图中合同号和合同名谁先谁后都没关系,但二者不可重复或同名)。
在对表的形式进行了规范化定义后,数据结构还有五种规范化定义,定名为规范化模式,称为范式。在这五种范式中,一般只用前三种,对于常用系统就足够了。而且这五种范式是“向上兼容”的,即满足第五范式的数据结构自动满足一、二、三、四范式,满足第四范式的数据结构自动满足第一、二、三范式,„„,依此类推。
第一范式(first normal form,简称1st NF)就是指在同一表中没有重复项出现,如果有则应将重复项去掉。这个去掉重复项的过程就称之为规范化处理。在本文所讨论的开发方法里,1st NF实际上是没有什么意义的。因为我们按规范化建立的指标体系和表的过程都自动保证了所有表都满足1st NF。
第二范式(second normal form,简称 2nd NF)是指每个表必须有一个(而且仅一个)数据元素为主关键字(primary key),其它数据元素与主关键字一一对应。例如,在图l9.7中如果我们将合同号定义为主关键字(其它数据元素中的记录数据都有可能重名,故不能作为主关键字),故只要知道了一个合同记录的合同号,就可以唯一地在同一行中找到该合同的任何一项具体信息。通常我们称这种关系为函数依赖(functional depEndence)关系。即表中其它数据元素都依赖于主关键字,或称该数据元素唯一地被主关键字所标识。
第三范式(third normal form,简称 3rd NF)就是指表中的所有数据元素不但要能够唯一地被主关键字所标识,而且它们之间还必须相互独立,不存在其它的函数关系。也就是说对于一个满足了 2nd NF的数据结构来说,表中有可能存在某些数据元素依赖于其它非关键宇数据元素的现象,必须加以消除。
为防止数据库出现更新异常、插入异常、删除异常、数据冗余太大等现象,关系型数据库要尽量按关系规范化要求进行数据库设计。
§2.3 SQL语言基础 2.3.1 SQL简介
用户对数据库的使用,是通过数据库管理系统提供的语言来实现的。不同的数据库管理系统提供不同的数据库语言。关系数据库管理系统几乎都提供关系数据库标准语言——SQL。SQL 的全称是Structured Query Language,即结构化查询语言。SQL语句可以从关系数据库中获得数据,也可以建立数据库、增加数据、修改数据。1986年ANSI采用SQL语言作为关系数据库系统的标准语言,后被国际化标准组织(ISO)采纳为国际标准。SQL语言使用方便、功能丰富、简洁易学,是操作数据库的工业标准语言,得到广泛地应用。例如关系数据库产品DB2、ORACLE等都实现了SQL语言。同时,其它数据库产品厂家也纷纷推出各自的支持SQL的软件或者与SQL的接口软件。这样SQL语言很快被整个计算机界认可。
SQL语言是一种非过程化语言,它一次处理一个记录集合,对数据提供自动导航。SQL语言允许用户在高层的数据结构上工作,而不对单个记录进行操作。SQL语言不要求用户指定数据的存取方法,而是使用查询优化器,由系统决定对指定数据存取的最快速手段。当设计者在关系表上定义了索引时,系统会自动利用索引进行快速检索,用户不需知道表上是否有索引或者有什么类型的索引等细节。SQL语言可以完成许多功能,例如: ● 查询数据
● 在数据库表格中插入、修改和删除记录 ● 建立、修改和删除数据对象 ● 控制对数据和数据对象的存取 ● 确保数据库的一致性和完整性等 2.3.2 SQL查询
数据查询是关系运算理论在SQL语言中的主要体现,SELECT 语句是SQL查询的基本语句,当我们在对一个数据库进各种各样的操作时,使用的最多的就是数据查询,在以SQL为基础的关系数据库中,使用的最多的就是SELECT查询语句。SELECT语句的完整句法如下: SELECT 目标表的列名或列表达式序列 FROM 基本表和(或)视图序列 [WHERE 行条件表达式] [GROUP BY 列名序列] [HAVING 组条件表达式] [ORDER BY列名 [ASC│DEAC]„] 我在SELECT语句中还使用了大量的保留字和通配符以进行各种各样的条件查询。在系统中有大量的查询按钮,其使用了大量的查询语句,而且这些查询语句大部分使用的是模糊查询,所以大量的使用了模式匹配符LIKE(判断值是否与指定的字符通配格式相符)。在包含LIKE的查询语句中可以使用两个通配符:%(百分号):与零个或多个字符组成的字符串匹配;_(下划线):与单个字符匹配。系统中的条件判断往往包含多个条件,这时就需要使用逻辑运算符NOT、AND、OR(用于多条件的逻辑连接),谓词ALL以及保留字DISTINCT等等。做为SELECT语句还有很多的使用方法,这里就不再叙述。2.3.3 SQL数据更新
使用数据库的目的是为了有效地管理数据,而数据的插入、删除和修改则是必不可少的一个功能。在本系统中就大量地使用了数据插入、删除和修改这三种操作,现做一个简单地介绍。●数据插入
往数据库的基本表中插入数据使用的是INSERT语句,其方式有两种:一种是元组值的插入,另一种是查询结果的插入。在本系统中使用的是前一种方式,其句法如下:
INSERT INTO 基本表名(列表名)VALUES(元组值)●数据删除
往数据库的基本表中删除数据使用的是DELETE语句,其句法如下: DELETE FROM 基本表名 [WHERE 条件表达式] 在些作一点说明,删除语句实际上是“SELECT * FROM 基本表名 [WHERE 条件表达式]”和DELETE操作的结合,每找到一个元组,就把它删除。此外,DELETE语句只能从一个基本表中删除元组,WHERE子句中条件可以嵌套,也可以是来自几个基本表的复合条件。●数据修改
当需要修改基本表中元组的某些列值时,可以用UPDATE语句实现,其句法如下: UPDATE基本表名
SET列名=值表达式[,列名=值表达式„] [WHERE条件表达式] 在Delphi中使用SQL语句是很方便的,一般来说,都是通过TQuery组件来使用SQL语言的。有一点要进行说明,虽然通过TQuery组件来使用SQL语言很方便,但考虑到自己对不同组件的理解程度、个人习惯以及其它各个方面,在本系统中我采用的是ADO组件来对数据库进行操作。最简单的方法比如在TADOQuery组件的SQL属性中就可以键入SQL语句,至于详细的使用方法在后面进行介绍。第三章 数据库开发工具 §3.1 Delphi 6.0 简介
Delphi类可以粗略地分成两部分:一部分是组件类,这些组件类通常以某种方式出现在组件面板上,当用户从组件面板上点取一个类的图标后,在程序中就自动生成了该类的对象(非可视组件除外);另一部分是功能类,这此功能类的对象通常出现在程序代码中,起着不可代替的作用,但是这些功能类在组件面板上是找不到的。在Delphi中,每一个类的祖先都是Tobject类,整个类的层次结构就像一棵倒挂的树,在最顶层的树根即为Tobject类。这样,按照面向对象编程的基本思想,就使得用户可用Tobject类这个类型代替任何其它类的数据类型。实际上在Delphi的类库中,Tobject类派生出了为数相当众多的子类,它们形成了一个庞大的体系,通常情况下,如果不自行开发组件,就不必了解整个类的体系结构,只用到类层次树的叶结点就足够了。
凡是做过程序开发的人都知道从来没有单纯的数据应用程序,也就是说,数据库应用程序必须和用户界面(可以是图形界面,也可以是命令接口)元素相结合,只讲界面或只讲数据库本身都构不成数据库应用程序,因而用Delphi 6.0开发数据库应用程序就隐含着界面开发。Delphi6中的VCL组件可用图3-1来说明。组件在Delphi程序的开发中是最显眼的角色。大家知道,在编写程序时一般都开始于在组件面板上选择组件并定义组件间的相互作用。但也有一些组件不在组件面板上,例如Tform和Tapplication(典型的非可视组件)。组件是Tcomponents派生出来的子类,可以流的形式存放在DFM文件中,具有事件和Publish属性。窗口组件类是窗口化的可视化组件类,在Delphi的类库中占有最大的份额。在实际编程中,窗口组件类的对象都有句柄,可以接受输入焦点和包含其它组件。图形组件与窗口组件并列,是另一大类组件。图形组件不是基于窗口的,因而不能有窗口句柄,不能接受输入焦点和包含其它组件。从图8-43中可以看出,图形组件的基类是TgraphicControl,在实际编程中,它们必须寄生于它们的宿主——窗口组件类的对象,由它们的拥有者负责其显示,而且它们还能触发一些和鼠标活动相关的事件。图形控件最典型的例子是Tlabel和TspeedButton。由此可以看出图形组件的功能很弱,有读者会问图形组件的用处何在呢?其实使用图形组件的最大好处在于节省资源,正是因为它们的功能较弱,所以使用的系统资源就要少。在一个应用程序中,如果能在不影响其功能的前提下合理大量地使用图形组件,将会大减少程序对系统资源的消耗。
非可视组件是与可视组件相并列的另一类组件,非可视组件在程序运行中是不可见的(除各种对话框组件之外,事实上有人认为对话框组件不能归入非可视组件,应该是另一种介于可视与非可视之间的组件)。§3.2 Delphi 6.0 控件
用Delphi6开发数据库应用,重点是和各种数据库组件打交道,当然也要使用其它的一些组件,现在就我在系统设计中所使用的重要组件给与简单介绍。3.2.1 ADO数据访问组件
ADO数据对象(Active Data Objects)实际是一种提供访问各种数据类型的链接机制。ADO设计为一种极简单的格式,通过ODBC的方法同数据库接口中,可以使用任何一种ODBC数据源,即不止适合于SQL Server、Oracle、Access等数据库应用程序,也适合于Excel表格、文本文件、图形文件和无格式的数据文件。ADO是基于OLE-DB之上的技术,因此ADO通过其内部的属性和方法提供统一的数据访问接口方法。ADO使您的客户端应用程序能够通过OLE DB提供访问和操作在数据库服务器中的数据。ADO支持用于建立C/S和Web的应用程序的主要功能。其主要优点是易于使用、高速度、低内存支出和占用磁盘空间较少。ADO同时具有远程数据服务(RDS)功能,通过RDS可以在一次往返过程中实现将数据从服务器移动到客户端应用程序和Web页、在客户端对数据进行处然后将更新结果返回服务器的操作。
Delphi 6.0继续对Microsoft的ADO访问能力的支持。这种能力是通过一组新组件实现的,这些组件是在企业版的ADO组件页中,在组件面版的ADO页上可以找到这些组件。利用在前面章节提到的TdataSet抽象类,ADO组件可以不通过BDE而直接实现ADO连接。这意味着只需要很少的代码就可以实现该连接并且性能得到提高。
利用ADO数据访问组件,可以只使用ADO结构与数据库取得联系并对其中的数据进行操作,而在这些过程中完全不需要使用BDE。大多数的ADO连接和数据集组件都是与基于BDE的连接和数据集组件相类似的。TADOConnection组件与基于BDE的应用程序中的Tdatabase组件类似。TADOTable与Ttable,TADOQuery与Tquery,以及TADOStoreProc和TstoredProc之间都具有这种类似的对应关系。使用这些ADO组件的方式与我们常使用的数据访问组件(基于BDE)都有许多相同之处。TTADODataSet没有直接的BDE对应组件,但它提供了许多与Ttable和Tquery相同的功能。同样,TADOCommand也没有相对应的BDE组件,它是在Delphi/ADO环境中完成特定功能的组件。Delphi 6.0通过ADO数据集访问组件,可以不借助BDE数据引擎而是通过微软的OLEDB来访问更为广泛的数据库中的数据。ADO数据集访问组件与常用的数据访问组件是并列的关系。在系统中我主要使用的是ADOTablet和ADOQuery两个组件。3.2.2 数据控制类DataControl 数据控制类负责数据库数据的显示,并把用户对数据的修改传回。这里的绝大多数组件,如DBText, DBEdit, DBMemo, DBImage, DBListBox, DBComboBox, DBCheckBox, DBRadioGroup, DBLookupListBox, DBLookupCombox, DBCtrGrid的功能和对应的非数据感知组件相同,如TEdit框,TRadioGroups单选按钮组等,只不过在显示数据库数据时要用而已。
在系统中主要使用数据网格控件DBGrid和数据库导航器控件DBNavigator。3.2.3 数据访问类DataAccess 数据库应用系统中数据访问是一个首要问题,包括单用户和 C/S系统,都必须联系一些数据库和数据表文件。Delphi 6 提供了专门用于数据访问的基类控件。主要包括数据源控件DataSource、客户数据集控件ClientDataSet、数据集提供器控件DataSetProvider等等。
Tdatabase:当一个基于BDE的数据库应用程序需要一个永久数据库连接时,需要定制向一个数据库服务器的连接时,需要事务控制和特殊的数据库别名时就得用到Tdatabase对象。特别是当连接到一个远程的SQL数据库服务器时,如果要利用BDE进行数据库事务处理,那么,TDatabase对象的威力就体现出来了。在一个应用程序中为每一个数据库连接显示的声明Tdatabase对象要根据需要而定,不是必需的。对一个数据库连接,如果没有显示的声明并实例化TDatabase对象,系统就会产生一个带有默认属性的TDatabase对象。
TdataSource对象用于在DataSet对象(包括Tquery,TstoredProc,Ttable等)和数据感知组件之间提供一个连接的纽带,以便在窗体上显示数据库中的数据,在数据库中导航定位与编辑数据集中的数据。如果一个DataSet对象中的数据想在数据感知组件中显示和修改,它就必须和TdataSource对象相联系。同样,一个数据感知组件如果想和数据源相联系以便显示和操纵数据,就必须以TDataSource对象为中介。
用Delphi6作数据库应用开发概括来说如下:先利用数据存取组件和实际的数据库建立连接,并用Tsession对象和Tdatabase对象管理这些连接。然后以Tdatasource对象为中介,用数据感知组件向用户显示数据库的内容并接受用户的查询和修改等操作。
3.2.4 SQL语言在Delphi中的应用
在Delphi中使用SQL语言非常方便,一般来说,都是通过Tquery组件来使用SQL语言的。可以在TQuery组件的SQL属性中设置SQL语句。设计程序时,在该组件的属性对话框中选择SQL属性,单击带省略号的按钮,就可以打开String List Editor对话框,然后我们就可以在对话框中添加SQL语句。还可以使用Delphi的SQL Builder来自动生成SQL语句,这样可以避免手工编写SQL而可能造成的语法错误。
静态SQL语句在程序设计时便已固定下来,它不包含任何参数和变量。动态SQL语句,也被称作参数化的语句,在其中间包含着表示字段名或表名的参数,例如下面的语句是一条动态SQL语句:
Select * From Students Where StudentCode =: StudentCode;其中的变量StudentCode便是一个参数变量,它由一个冒号引导,在程序运行过程中,必须要为该参数赋值,该条SQL语句才能正确执行,每次运行应用程序时可以为该参数变量赋予不同的值。为参数赋值有三种方法:
①根据参数在SQL语句中出现的顺序,设置TQuery部件的Params属性值为参数赋值。
②直接根据SQL语句中各参数的名字,调用ParamByName方法来为各参数赋值。③将TQuery部件的DataSource属性设置为另一个数据源,这样将另一个数据源中与当前TQuery部件的SQL语句中的参数名相匹配的字段值赋给其对应的参数。利用这种方法也能实现所谓的连接查询,创建主要—明细型数据库应用。在程序运行过程中,要想设置TQuery部件的SQL属性,必须首先调用Close方法,关闭TQuery部件,然后再调用Clear方法清除SQL属性中现存的SQL命令语句,最后再调用Add方法为SQL属性设置新的SQL命令语句。例如: Query1.Close {关闭Query1)Query1.SQL.Clear {清除SQL属性中的SQL命令语句} Query1.SQL.Add(‘Select * From Students‘);Query1.SQL.Add(‘ Where Name =“Lucy” ‘);
在为TQuery部件设置SQL属性时调用Close方法总是很安全的,如果TQuery部件已经被关闭了,调用Close方法时不会产生任何影响。在应用程序中为SQL属性设置新的SQL 命令语句时,必须要调用Clear方法以清除SQL属性中现存的SQL命令语句,如果不调用Clear方法,便调用Add方法向SQL属性中设置SQL命令语句,那么新设置的SQL命令语句会追加在现存SQL命令语句后面,在程序运行时常常会出现出乎意料的查询结果甚至程序无法运行下去。
在这里要特别注意的,一般情况下TQuery部件的SQL属性只能包含一条完整的SQL语句,它不允许被设置成多条SQL语句。当然有些数据库服务器也支持在TQuery部件的SQL属性中设置多条SQL语句,只要数据库服务器允许这样,我们在编程时可以为 SQL 属性设置多条SQL语句。
在为TQuery部件设置完SQL属性的属性值之后,也即编写好适当的SQL程序之后,可以有多种方式来执行SQL程序。
在设计过程中,设置完TQuery部件的SQL属性之后将其Active属性的值置为True,这样便可以执行SQL属性中的SQL程序,如果应用中有与TQuery部件相连的数据浏览部件(如TDDGrid TDBEdit等)那么在这些数据浏览部件中会显示SQL程序的执行结果。
在应用程序运行过程中,通过程序调用TQuery部件的Open方法或ExecSQL 方法可以执行其SQL属性中的SQL程序。Open方法和ExecSQL方法是不一样的。Open方法只能用来执行SQL语言的查询语句(Select命令),并返回一个查询结果集,而ExecSQL方法还可以用来执行其它常用的SQL语句(如INSERT, UPDATE, DELETE等命令),例如:
Query1.Open(这样会返回一个查询结果集)如果调用Open方法,而没有查询结果时,会出错。此时应该调用ExecSQL 方法来代替Open方法。如: Query1.ExecSQL(没有返回结果)当然在设计应用程序时,程序设计人员是无法确定TQuery部件中的SQL 语句是否会返回一个查询结果的。对于这种情况应当用Try„Except模块来设计程序。在 Try 部分调用Open方法,而在Except部分调用ExceSQL方法,这样才能保证程序的正确运行。
Delphi中用ADOQuery来使用SQL语句同样十分方便。在ADOQuery组件中首先通过ConnectionString属性值来联接数据源,然后就通过双击SQL„属性值来写入SQL语句。在Delphi中调用数据库,就可以调用ADOQuery组件,通过修改其中的SQL„属性中的SQL语句来实现对数据库的各项操作。
值得注意的是,ADOQuery组件只有在激活的情况下才可以被正确地使用,这样就提出了一个问题,也就是说,在每次修改ADOQuery组件的SQL„属性时都必须先行进行关闭,待清除掉SQL„中所有的SQL语句后才可以添加新的SQL语句。而且,在每一次修改完成以后,还应该记得重新将ADOQuery激活。其它的使用方法与TTQuery有许多的相似之处。§3.3 Access 简介
建立一个数据库我们有多种选择,现在市场上有各种各样的数据库,而且每一种数据库都有其自身的特点,不能说哪一种更好,只能在其中寻找一种能更好地适应系统需求、更好地满足用户的要求以及适应开发人员的习惯。在本系统中,做为图书仓库管理系统是一个比较小的应用系统,它所产生和处理的数据量也比较小。因此,没有必要使用像SQL Server和Oracle这样的大型数据库。我首先想到的数据库是Borland公司的Paradox数据库。另外,Microsoft Office中的Access数据库在计算机上的应用比较普及,是开发小型数据库系统的比较理想的选择,所以,在本系统中我选择了Access数据库。
Access做为一个数据库管理系统,它被集成在Microsoft Office中。Access数据库处理的基本结构,采取关系型数据库模式。与其他的数据库系统相比,Access更加简单易学,一个普通的计算机用户可以很快地掌握它。Access 2000的功能十分强大,利用它可以方便地实现对信息保存、维护、查询、统计、打印、交流、发布,而且它可以十分方便地与Office其他组件交流数据,这些功能对一个一般用户而言已经足够了 第四章 系统总体设计
软件系统的总体设计大约要经历可行性分析和项目开发计划,需求分析,概要设计,详细设计,编码,测试以及维护等七个阶段。可行性分析和项目开发计划在前面已经叙述,下面所要做的是进行软件需求分析,概要设计和详细设计。编码过程将在下一节论述,而测试和维护过程不在本文叙及。§4.1 系统需求分析
在经过前一阶段的分析之后,我确定了我的开发课题为图书仓库管理。现在所要做的是要准确定义系统必须做什么以及系统必须具备的功能。
软件需求分析中我采用结构化分析方法(Structured Analysis,简称SA),SA是面向数据流进行需求分析的方法,像所有的软件分析方法(如面向对象分析方法、IDEF方法等等)一样,SA也是一种建模活动,它使用简单易读的符号,根据软件内部数据传递、变换的关系,自顶向下逐层分解,描绘满足功能要求的软件模型。
在系统中我采用数据流图(DFD)这种半形式化的描述方式表达需求。它是一种功能模型,以图形的方式描绘数据在系统中流动和处理的过程,只反映系统必须完成的逻辑功能。它有四种基本图形符号: ◆ →:箭头,表示数据流; ◆ 〇:圆或椭圆,表示加工; ◆ ═:双杠,表示数据存储;
◆ □:方框,表示数据的源点或终点。
为了表达较为复杂问题的数据处理过程,用一张数据流图是不够的,要按照问题的层次结构进行逐步分解,并以一套分层的数据流图反映这种结构关系。在这里我一共使用了三层数据流图,即顶层图,0层图和1层图(也是底层图)。在多层数据流图中,顶层流图仅包含一个加工,它代表被开发系统,它的输入流是该系统的输入数据了,输出流是该系统的输出数据;底层流图是指其加工不需要再做分解的数据流图,中间层流图表示对其上层父图的细化,它的每一步加工可能继续细化成子图。
经过对系统的分析首先得到系统的顶层DFD,如下: 一步细化得到系统的0层DFD,如下:
再进一步细化每一个数据加工功能,得到系统的1层DFD图。
在这里只给出有关入库管理和出库管理的1层数据流图,它们是系统的关鍵部分,也是主要的部分。通过以上对数据流图的分析之后,我们已大体地了解了系统的功能和目标,接下来所要做的就是系统功能模块的划分和数据库的设计,也就是系统的概要设计。§4.2 系统概要设计
在软件需求分析阶段,搞清楚了软件“做什么”的问题,形成了目标系统的逻辑模型。现在我们所要做的就是要把软件“做什么”的逻辑模型变换为“怎么做”的物理模型,即着手实现软件的需求。首先,我们需要描述的是系统的总的体系结构。
4.2.1 系统结构设计
系统的概要设计中最重要的就是系统的模块化。模块化是指解决一个复杂问题时自项向下逐层把软件系统划分成若干个模块的过程。每个模块完成一个特定的功能,所有的模块按某种方法组织起来,成为一个整体,完成整个系统所要求的功能。
将系统划分为多个模块是为了降低软件系统的复杂性,提高可读性、可维护性,但模块的划分不能是任意的,应尽量保持其独立性。也就是说,每个模块只完成系统要求的独立的子功能,并且与其他模块的联系最少且接口简单,即尽量做到高内聚低耦合,提高模块的独立性,为设计高质量的软件结构奠定基础。在系统的概要设计中我采用结构化设计(Structure Design,简称SD),SD以需求分析阶段产生的数据流图DFD为基础,按一定的步骤映射成软件结构。我首先将整个系统化分为几个小问题,小模块,在系统中,我设计了用户管理、库存管理、入库管理、出库管理、员工管理和供应商管理6个小模块。然后,进一步细分模块,添加细节。比如,用户管理我又将其分为用户注册、用户注销、密码修改;库存管理分为库存记录查询、库存记录修改、库存记录打印等等。以下就是系统的结构图:(在这里为了表达方便我将结构图分开来表达。)
在得到系统的第一层功能模块图后,经过进一步地细化,得一系统的子功能模块图:
4.2.2 数据库设计
在信息世界中,信息从客观事物出发流经数据库,通过决策机构最后又回到客观世界,信息的这一循环经历了三个领域:信息世界,数据世界,现实世界。现实世界的事物反映到人的头脑中,人的大脑对它有个认识过程,经过分析(选择、命名、分类等)进入信息世界。这些信息再进一步加工、编码,然后进数据世界,而软件系统的开发工作需要考虑这两个方面的问题,也就是要考虑系统开发所需要的数据,以及如何对这些数据进行操作。这两个问题贯穿了整个软件系统的开发过程,这也就是数据库的设计问题,软件设计的一个核心。4.2.2.1 ER图设计
在系统设计的开始,我首先考虑的是如何用数据模型来数据库的结构与语义,以对现实世界进行抽象。目前广泛使用的数据模型可分为两种类型,一种是独立于计算机系统的“概念数据模型”,如“实体联系模型”;另一种是直接面向数据库逻辑结构的“结构数据模型”。在本系统中我采用“实体联系模型”(ER模型)来描述数据库的结构与语义,以对现实世界进行第一次抽象。ER模型直接从现实世界抽象出实体类型及实体间联系,然后用ER图来表示数据模型。它有两个明显的优点:接近于人的思维,容易理解;与计算机无关,用户容易接受。但ER模型只能说明实体间语义的联系,不能进一步说明详细的数据结构,它只是数据库设计的第一步。
ER图是直观表示概念模型的工具,它有四个基本成分: ◆ 矩形框,表示实体类型(考虑问题的对象)。◆ 菱形框,表示联系类型(实体间的联系)。
◆ 椭圆形框,表示实体类型和联系类型的属性。对于关键码的属性,在属性名下划一横线。
◆直线,联系类型与其涉及的实体类型之间以直线连接。
本系统为图书仓库管理,主要管理图书的入库、出库以及库存等事项。仓库根据需要可以查询图书供应商的信息,同时还需要了解在入库和出库中员工的参与情况。依据仓库管理的实际情况,考虑了多方面的因素以后,确定系统的ER图如下:
(为了表达的方便,在这里我没有在一张图上表达出所有的关系,而是用一张总体ER图,和几张实体属性关系图来表达数据库的结构。)
在该数据库中,我设计了三个实体,分别是库存、员工和供应商以及两个联系类型入库和出库。在本系统中库存是核心,也是基本,没有了库存其它的也就没有什么意义了。员工记录的添加是考虑到责任问题,也就是说,在仓库管理的实际运用中,出现了责任不清的现象,特别是由于仓库的进出图书数量都比较大时产生了一系列问题,所以在设计数据库时,我特别考虑到这一点,加入了员工记录这一实体。供应商信息的添加主要出于对图书来源问题的思考。通过添加供应商信息可以比较清楚地了解图书的进货渠道,从图书的质量到供应商的信誉都可以进行了解,同时可以为以后的图书进购提供一定有用的信息。
入库联系类型将库存信息、供应商信息和员工信息联系在一起,可以方便地实现三个实体之间的联接,而出库联系类型则将库存信息和员工信息较好地联接起,同时这两个联系类型又都具有各自特有的属性。下面就是各实体及联系类型的属性图:(带#号的属性为关键字段)4.2.2.2 数据库表格设计
在完成系统的ER图之后,需要将ER模型转化为关系模型,也就是说,要设计出数据库所需要的表格。在这里,我选用的是关系数据库。因为关系数据库中的二维表格可以很清楚地描述数据之间的联系。
在这里不得不提到一个概念——范式。其实在上一节的ER图设计中,已经运用了范式的思想,不仅如此,在数据库的表格设计中更离不开范式的思想,它是数据库设计的基础,如果不注意这个问题将会导致一系列问题的出现。
我在系统中定义的表格都严格地按照范式的思想和要求去完成,数据库中的所有表格都达到了三范式的要求。根据系统ER图,针对本系统的特点,在对所搜集的数据进行规范化之后,定义了如下六张表格,分别是库存信息表,入库信息表,出库信息表,员工信息表,供应商信息表和密码信息表。通过对这六张表格的操作可以较好地完成系统设计的各项功能,六张表格之间有着不同程度的联系。(说明:在以下数据表中,K代表主键,#代表外键,字段值不为空。)BookRecord 表(库存信息表)
字段名称 数据类型 说明 K BookID 数字 图书编号 BookName 文本 图书名 Author 文本 作者 Publisher 文本 出版社 PubDate 日期/时间 出版日期 Price 货币 价格 BookType 文本 图书类型 Number1 数字 库存数量 Addation 文本 备注 图4.13 库存信息表 库存信息表主要用于记录仓库中现存放的所有图书的详细信息,包括图书编号、书名、作者、出版社、图书类型等有关图书的各类信息,它即是该数据库的主表,也是系统主界面的主要内容。
在该表中图书编号是主键,它按图书入库的先后次序来编写,每当有图书入库,系统自动给出图书编号,这样我们按图书编号来查找图书是比较方便的。考虑到编号比较难于记忆,所以使用了出版社和图书类型两个字段,在系统中我提供了出版社和图书类型的分类查找,而且全部采用自动生成,每当系统中有新的出版社类型和图书类型,弹出菜单会自动添中新类型,这样就可以比较方便地实现按出版社和按图书类型查找。此外,库存数量也是一个比较关键的字段,该字段是在系统初始化时就给定的,每当有图书入库或出库操作,系统就会自动修改图书的库存数量,以保持数据的一致性。做为备注有一点说明,我的数据库中备注的数据类型是文本,而不是备注类型,主要考虑到该字段的长度并不大,而且在Delphi中文本数据类型的处理也比较方便一点。Employee 表(员工信息表)
字段名称 数据类型 说明 K EmployeeID 数字 员工编号 EmployeeName 文本 员工姓名 Sex 文本 性别
BornDate 日期/时间 出生日期 Grade 文本 职称
WorkDate 日期/时间 工作日期 Telephone 文本 联系电话 Address 文本 联系地址
图4.14 员工信息表
员工信息表主要用于记录有关员工的各类信息,包括姓名、职称、出生日期、联系电话、联系地址等。它主要用来为系统提供员工的有关信息,因为在系统中,入库和出库操作均与员工有着一定的联系,在查询入库信息和出库信息时,有时需要查找有关此项记录有关的员工信息,在系统中我是通过入库记录与员工记录(出库记录和员工记录)之间的联接查询来完成的。另外,作为一个仓库也有必要了解其所属员工的一些基本情况,以便查询。Shopkeeper 表(供应商信息表)
字段名称 数据类型 说明 K ShopkeeperID 数字 供应商编号 ShopkeeperName 文本 供应商姓名 Address 文本 地址 PostNo 数字 邮编
OfficePhone 文本 办公电话 HomePhone 文本 住宅电话 Email 文本 E-mail PayType 文本 付款方式
图4.15 供应商信息表
供应商信息表主要用于记录有关供应商的各类信息,包括姓名、地址、电话、付款方式等。它主要用来为系统提供供应商的有关信息,在系统中入库记录是与供应商记录相联系的,通过入库记录可以查找相关的供应商信息。在供应商信息中,考虑当实际情况,我特别加入了Email和付款方式这两个字段,因为在当今信息世界中,多种多样的通讯方式和多种多样的付款方式是必然的,是数据库中必须与以记录。
InRecord 表(入库信息表)
字段名称 数据类型 说明 K InID 数字 入库编号 # BookID 数字 图书编号 # EmployeeID 数字 员工编号 # ShopkeeperID 数字 供应商编号 Number 数字 入库数量 BuyDate 日期/时间 入库日期
图4.16 入库信息表
OutRecord 表(出库信息表)
字段名称 数据类型 说明 K OutID 数字 出库编号 # BookID 数字 图书编号 # EmployeeID 数字 员工编号 Number2 数字 出库数量 OutDate 日期/时间 出库日期
图4.17 出库信息表
入库信息表主要用于记录有关入库的详细信息,包括入库数量、入库日期以及图书、员工、供应商三方的编号,以便查询。出库信息表主要用于记录有关出库的详细信息,包括出库数量、出库日期以及图书、员工的编号。出库信息表和入库信息表一样,其实它们都属于联系类型,系统通过这两个表可以联接上其它的表为用户提供多种条件的联接查询。值得提出的一点是入库记录和出库记录的添加不仅仅是单表操作,由于它们都与库存记录相联系,所以,无论您是添中入库记录还是添加出库记录,都必须同时修改库存记录,以保持数据的一致性,否则将引发系统出错而这些我都让其在系统中自动完成。无论您是添加入库记录,还是添加出库记录,系统都将自动修改库存中图书的数量,而且,在您出库的数量大于库存数量时,系统还会自动提示错误,这样就可以防止一定错误的发生。在入库信息表和出库信息表中我还定义了几个外键,它提供了一种表示几个关系联系的方法。比如,系统中通过在入库信息表中定义的外键 BookID、EmployeeID和ShopkeeperID可以将库存信息表、员工信息表和供应商信息表联系在一起,从而方便地实现联接查询,而且,引入外键的定义是实体完整性约束的一个主要方面。
Key 表(密码信息表)
字段名称 数据类型 说明 K KeyName 文本 用户姓名 KeyNo 文本 用户密码 图4.18 密码信息表
密码信息表主要用于记录所有的用户名和用户密码。它是在用户登陆时用来确定用户和密码的正确性,以防止非法用户登陆。
通过以上设计已经完成了系统的概要设计,当我们有了系统的功能模块图和数据库之后,就需要着手去实现每一个模块,为每一个功能设计程序流程图,这也就是系统的详细设计。§4.3 系统详细设计
在前面的概要设计中,已将系统划分为多个模块,并将它们按照一定的原则组装起来,同时确定了每个功能及模块之间的外部接口。现在所要做的就是确定每个模块具体执行过程,也可以说是“过程设计”。
在处理过程设计时我采用的是结构化程序设计(简称SP)方法。需要指出的是系统的详细设计并不是指具体的编程序,而是将概要设计阶段产生的系统功能模块图细化成很容易产生程序的图纸。因此详细设计的结果基本决定了最终程序的质量。为软件的质量,延长软件的生存期,软件的可测试性、可维护性提供重要的保障。详细设计的目标不仅是逻辑上正确地实现每个模块的功能,还应使设计出的处理过程清晰易读。
由前一阶段产生的系统功能模块图,我为系统的主要部分设计了如下程序流程图:通过以上步骤,基本上完成了对整个系统的总体设计,接下来所要做的就是软件的编码工作。系统总体设计的好坏直接影响着下一步工作,只有在这一阶段设计出好的模块图和程序流程图,才能更有利于编码,产生好的软件系统。
第五章 系统应用程序设计 §5.1 系统窗体模块组成 §5.2 数据模块窗体的设置
在编写数据库应用程序时,经常要遇到这样的情况,即好多组件、窗体同时访问相同的数据源,如果为每一个组件或者窗体都设置一个数据源将是十分耗时的工件,而且要保证这些数据源的确是相同的也需花一番功夫。那么,能不能将这些数据源集中管理,最好是做成一个统一的模块,需要时就将该模块引入而不必直接操作数据源本身呢?数据模块(DataModule)是解决这个问题最好的答案。简单说来,数据模块是用来集中管理数据源的一个窗体,该窗体可被需要的地方随时引入。
图5.2给出了本程序的数据模块(datamoduleform)窗体图,除报表窗体外所有的数据存取组件和数据源组件都在此数据模块中进行了定义。值得一提的是,设置了数据库Database组件,该组件引入了系统所需的唯一的数据库tsxs,Database组件的DatabaseName属性设置为tsckgl。tsxs数据库已在ODBC配置程序中进行了设置。其他的数据存取组件都是基于此数据库组件创建的,这样做的好处是,当数据库的别名或者其他信息改变之后,只需修改Tdatabase组件的AliasName属性即可。
另外,在本系统的数据模块窗体图中,我大多采用的AODQuery组件而没有采用BDE组,这主要是基于对ADO组件的了解。在Delphi的学习中我对ADO组件了解的更加清楚,使用也较BDE更为熟练,而且,ADO组件的功能也较BDE更为强大,所以在这里大多采用ADO组件来进行数据库联接。同时我也使用了BDE组件中的Table,因为在某些时候BDE有着其自身特有的优越性。主窗体功能模块的实现 file://主窗体程序代码
public file://在程序的起始部分,定义快捷按钮点击事件 Procedure Popup1Handler(Sender:Tobject);Procedure Popup2Handler(Sender:TObject);********************************************************************** procedure Tmainform.Popup1Handler(Sender: TObject);begin file://快捷按钮1(点“按出版社分类”按钮产生)的点击事件 with datamoduleform.MainQuery do begin file://打开数据模块窗体的MainQuery,对BookRecord表进行操作 close;file://关闭MainQuery SQL.Clear;file://清除SQL属性中的SQL命令语句
SQL.Add(‘select * from BookRecord where Publisher=:Pub‘);file://添加新的SQL语句
Parameters.ParamByName(‘Pub‘).Value:=(Sender as TMenuItem).Caption;open;file://重新打开MainQuery end;end;********************************************************************** procedure Tmainform.SpeedButton1Click(Sender: TObject);Var s1,s2,s3,s4,s5 :String;file://设立5个变量以方便实现模糊查询 begin file://主窗口库存查询按钮事件 with datamoduleform.MainQuery do begin close;SQL.Clear;SQL.Add(‘select * from BookRecord‘);
SQL.Add(‘where BookID Like :BookID and BookName Like :Name and Author Like :Author and Publisher Like :pub and BookType Like :BookType‘);file://使用Like语句来实现模糊查询
if Edit1.Text<>‘‘ then s1:=‘%‘+Edit1.Text+‘%‘ else s1:=‘%‘;
Parameters.ParamByName(‘BookID‘).Value:=s1;file://给变量s1赋值
if Edit2.Text<>‘‘ then s2:=‘%‘+Edit2.Text+‘%‘ else s2:=‘%‘;
Parameters.ParamByName(‘Name‘).Value:=s2;file://给变量s2赋值
if Edit3.Text<>‘‘ then s3:=‘%‘+Edit3.Text+‘%‘ else s3:=‘%‘;
Parameters.ParamByName(‘Author‘).Value:=s3;file://给变量s2赋值
if Edit4.Text<>‘‘ then s4:=‘%‘+Edit4.Text+‘%‘ else s4:=‘%‘;
Parameters.ParamByName(‘Pub‘).Value:=s4;file://给变量s2赋值
if Edit5.Text <>‘‘ then s5:=‘%‘+Edit5.Text+‘%‘ else s5:=‘%‘;
Parameters.ParamByName(‘BookType‘).Value:=s5;file://给变量s2赋值 open;if FieldValues[‘BookID‘]=NULL file://判断是否找到记录 then begin Messagedlg(‘没有找到你所需要的记录!‘,mtInformation,[mbOK],0);Edit1.Text:=‘‘;Edit2.Text:=‘‘;Edit3.Text:=‘‘;Edit4.Text:=‘‘;Edit5.Text:=‘‘;close;SQL.Clear;SQL.Add(‘select * from BookRecord‘);file://这里相当于一个刷新功能 open;end;end;end;********************************************************************** procedure Tmainform.SpeedButton3Click(Sender: TObject);begin file://库存表刷新按钮事件 with datamoduleform.MainQuery do begin close;SQL.Clear;SQL.Add(‘select * from BookRecord‘);open;end;end;********************************************************************** procedure Tmainform.SpeedButton11Click(Sender: TObject);var PopupItem:TMenuItem;begin file://自动生成快捷按钮1的内容 with datamoduleform.BookQuery do begin file://从数据库中选择出版社类型 close;SQL.Clear;SQL.Add(‘select distinct Publisher from BookRecord‘);open;PopupMenu1:=TPopupMenu.Create(Self);file://自动生成快捷菜单 PopupMenu1.AutoHotkeys:=maManual;file://自定义热键 while Not Eof do begin file://根据出版社内容生成菜单子项 PopupItem:=TMenuItem.Create(Self);PopupItem.Caption:=FieldByName(‘Publisher‘).AsString;PopupMenu1.Items.Add(PopupItem);PopupItem.onClick:=Popup1Handler;file://确定菜单子项的点击事件 Next;end;end;PopupMenu1.Popup(384,67);file://在指定位置显示快捷菜单1 end;********************************************************************** procedure Tmainform.FormActivate(Sender: TObject);begin file://系统初始化,在进入mainform时自动添加数据源 mainform.DBGrid1.DataSource:=datamoduleform.MainSource;mainform.DBNavigator1.DataSource:=datamoduleform.MainSource;mainform.DBGrid2.DataSource:=datamoduleform.EmpSource;mainform.DBNavigator2.DataSource:=datamoduleform.EmpSource;mainform.DBGrid3.DataSource:=datamoduleform.ShopSource;mainform.DBNavigator3.DataSource:=datamoduleform.ShopSource;mainform.DBGrid4.DataSource:=datamoduleform.InSource;mainform.DBNavigator4.DataSource:=datamoduleform.InSource;mainform.DBGrid5.DataSource:=datamoduleform.OutSource;mainform.DBNavigator5.DataSource:=datamoduleform.OutSource;end;********************************************************************** procedure Tmainform.FormCreate(Sender: TObject);begin file://系统初始化,定义界面大小,以适应不同分辩率 Width:=800;Height:=600;end;********************************************************************** procedure Tmainform.Timer1Timer(Sender: TObject);begin file://在状态栏显示时间 StatusBar1.Panels[2].Text:=DateToStr(Date);StatusBar1.Panels[4].Text:=TimeToStr(Time);end;§5.4 入库、出库窗体模块的实现
图5.4 系统入库管理窗体
图5.5 系统出库管理窗体 procedure Tinoutform.SpeedButton4Click(Sender: TObject);begin file://入库管理查找按钮事件
with datamoduleform.BookQuery do file://入库查询处理 begin close;SQL.Clear;SQL.Add(‘select * from BookRecord where BookID=:BookID‘);
Parameters.ParamByName(‘BookID‘).Value:=Edit13.Text;open;if FieldValues[‘BookID‘]<>NULL then begin Edit1.Text:=‘‘;
Edit1.ReadOnly:=true;Edit1.Color:=clMenu;Edit6.Text:=FieldValues[‘BookName‘];file://显示图书名 Edit6.ReadOnly:=true;Edit6.Color:=clMenu;file://设置显示框不可更改属性
Edit7.Text:=FieldValues[‘Author‘];Edit7.ReadOnly:=true;Edit7.Color:=clMenu;Edit8.Text:=FieldValues[‘Publisher‘];Edit8.ReadOnly:=true;Edit8.Color:=clMenu;Edit9.Text:=FieldValues[‘PubDate‘];Edit9.ReadOnly:=true;Edit9.Color:=clMenu;Edit10.Text:=FieldValues[‘Price‘];Edit10.ReadOnly:=true;Edit10.Color:=clMenu;Edit11.Text:=FieldValues[‘BookType‘];Edit11.ReadOnly:=true;Edit11.Color:=clMenu;Edit12.Text:=FieldValues[‘Number1‘];Edit12.ReadOnly:=true;Edit12.Color:=clMenu;If FieldValues[‘Addation‘]<>NULL then Edit25.Text:=FieldValues[‘Addation‘]
else Edit25.Text:=‘‘;
Edit25.ReadOnly:=true;Edit25.Color:=clMenu;end else begin file://在没有查找到的情况下,清空所有显示框 Edit1.ReadOnly:=false;Edit1.Text:=‘‘;Edit1.Color:=clMenu;
Edit6.ReadOnly:=false;Edit6.Text:=‘‘;Edit6.Color:=clMenu;
Edit7.ReadOnly:=false;Edit7.Text:=‘‘;Edit7.Color:=clMenu;
Edit8.ReadOnly:=false;Edit8.Text:=‘‘;Edit8.Color:=clMenu;Edit9.ReadOnly:=false;Edit9.Text:=‘‘;Edit9.Color:=clMenu;
Edit10.ReadOnly:=false;Edit10.Text:=‘‘;Edit10.Color:=clMenu;
Edit11.ReadOnly:=false;Edit11.Text:=‘‘;Edit11.Color:=clMenu;
Edit12.ReadOnly:=false;Edit12.Text:=‘‘;Edit12.Color:=clMenu;Edit25.ReadOnly:=false;Edit25.Text:=‘‘;Edit25.Color:=clMenu;
MessageDlg(‘没有找到你所需要的记录!‘,mtInformation,[mbOK],0);Edit13.Text:=‘‘;Edit13.SetFocus;end;end;with datamoduleform.InQuery do file://自动入库编号的获取 begin close;SQL.Clear;SQL.Add(‘select * from InRecord where InID>=All(select InID from InRecord)‘);
open;file://找到入库编号中最大的一个 Edit26.ReadOnly:=false;Edit26.Text:=FieldValues[‘InID‘]+1;file://最大的入库编号加1形成新的入库编号
Edit26.ReadOnly:=true;Edit26.Color:=clMenu;file://设置编号的不可更改性 end;end;********************************************************************** procedure Tinoutform.SpeedButton1Click(Sender: TObject);var s:integer;begin file://入库管理添加按钮事件 if Edit1.Text<>NULL then MessageDlg(‘请输入完整的入库信息和图书信息,然后单击确定按钮。‘, mtInformation,[mbok],0)else begin if(Edit2.Text=‘‘)or(Edit3.Text=‘‘)or(Edit4.Text=‘‘)or(Edit5.Text=‘‘)then begin MessageDlg(‘请输入完整的入库信息!‘,mtInformation,[mbok],0);Edit2.SetFocus;end else begin with datamoduleform.InQuery do file://将找到的图书信息显示 begin close;SQL.Clear;SQL.Add(‘insert into InRecord values(:InID,:BookID,:EmpID,:ShopID, :Number,:InDate)‘);file://向入库信息表中插入记录
Parameters.ParamByName(‘InID‘).Value:=Edit26.Text;file://向Edit框取值
Parameters.ParamByName(‘BookID‘).Value:=Edit13.Text;
Parameters.ParamByName(‘EmpID‘).Value:=Edit2.Text;
Parameters.ParamByName(‘ShopID‘).Value:=Edit3.Text;
Parameters.ParamByName(‘Number‘).Value:=Edit4.Text;
Parameters.ParamByName(‘InDate‘).Value:=Edit5.Text;execSQL;end;Edit12.ReadOnly:=False;S:=StrToInt(Edit12.Text)+StrToInt(Edit4.Text);file://计算入库后库存图书数量
Edit12.Text:=IntToStr(s);file://将修改后的库存图书数量显示 Edit12.ReadOnly:=true;with datamoduleform.BookQuery do file://修改库存记录中图书数量
begin close;SQL.Clear;SQL.Add(‘update BookRecord set Number1=:Number where BookID=:BookID‘);
Parameters.ParamByName(‘Number‘).Value:=s;
Parameters.ParamByName(‘BookID‘).Value:=Edit13.Text;execSQL;file://提交SQL语句
MessageDlg(‘记录已成功添加!‘,mtInformation,[mbOK],0);Edit13.SetFocus;end;end;end;end;********************************************************************** procedure Tinoutform.SpeedButton2Click(Sender: TObject);begin file://入库管理确定按钮事件
if(Edit2.Text=‘‘)or(Edit3.Text=‘‘)or(Edit4.Text=‘‘)or(Edit5.Text=‘‘)
or(Edit6.Text=‘‘)or(Edit7.Text=‘‘)or(Edit8.Text=‘‘)or(Edit9.Text=‘‘)
or(Edit10.Text=‘‘)or(Edit11.Text=‘‘)or(Edit25.Text=‘‘)then begin file://判断输入信息的完整性
MessageDlg(‘请输入所需的全部入库信息!‘,mtInformation,[mbok],0);Edit2.SetFocus;end else begin with datamoduleform.InQuery do file://入库信息添加 begin close;SQL.Clear;SQL.Add(‘insert into InRecord values(:InID,:BookID,:EmpID,:ShopID, :Number,:InDate)‘);file://向入库信息表中插入记录
Parameters.ParamByName(‘InID‘).Value:=Edit26.Text;
Parameters.ParamByName(‘BookID‘).Value:=Edit1.Text;Parameters.ParamByName(‘EmpID‘).Value:=Edit2.Text;
Parameters.ParamByName(‘ShopID‘).Value:=Edit3.Text;
Parameters.ParamByName(‘Number‘).Value:=Edit4.Text;
Parameters.ParamByName(‘InDate‘).Value:=Edit5.Text;execSQL;end;with datamoduleform.BookQuery do begin close;SQL.Clear;file://在完成入库信息的添加后,修改库存记录 SQL.Add(‘insert into BookRecord values(:BookID,:BookName,:Author, :Publisher,:PubDate,:Price,:BookType,:Number,:Addration)‘);
Parameters.ParamByName(‘BookID‘).Value:=Edit1.Text;Parameters.ParamByName(‘BookName‘).Value:=Edit6.Text;Parameters.ParamByName(‘Author‘).Value:=Edit7.Text;
Parameters.ParamByName(‘Publisher‘).Value:=Edit8.Text;
Parameters.ParamByName(‘PubDate‘).Value:=Edit9.Text;Parameters.ParamByName(‘Price‘).Value:=Edit10.Text;
Parameters.ParamByName(‘BookType‘).Value:=Edit11.Text;
Parameters.ParamByName(‘Number‘).Value:=Edit4.Text;
Parameters.ParamByName(‘Addration‘).Value:=Edit25.Text;execSQL;end;MessageDlg(‘记录添加成功!‘,mtInformation,[mbok],0);end;end;********************************************************************** procedure Tinoutform.SpeedButton11Click(Sender: TObject);begin file://新书入库按钮事件
Edit13.Text:=‘‘;Edit13.Color:=clMenu;with datamoduleform.InQuery do file://自动入库编号的获取 begin close;SQL.Clear;SQL.Add(‘select * from InRecord where InID>=All(select InID from InRecord)‘);open;Edit26.Text:=FieldValues[‘InID‘]+1;Edit26.ReadOnly:=true;Edit26.Color:=clMenu;end;with datamoduleform.BookQuery do file://自动图书编号的获取 begin close;SQL.Clear;SQL.Add(‘select * from BookRecord where BookID>=All(select BookID from BookRecord)‘);file://找到库存图书编号中最大的一个 open;Edit1.ReadOnly:=false;Edit1.Text:=FieldValues[‘BookID‘]+1;file://显示自动生成的图书编号
Edit1.ReadOnly:=true;Edit1.Color:=clMenu;end;
Edit2.Text:=‘‘;Edit3.Text:=‘‘;Edit4.Text:=‘‘;Edit5.Text:=‘‘;
Edit6.ReadOnly:=false;Edit6.Text:=‘‘;Edit6.Color:=clWindow;Edit7.ReadOnly:=false;Edit7.Text:=‘‘;Edit7.Color:=clWindow;
Edit8.ReadOnly:=false;Edit8.Text:=‘‘;Edit8.Color:=clWindow;
Edit9.ReadOnly:=false;Edit9.Text:=‘‘;Edit9.Color:=clWindow;
Edit10.ReadOnly:=false;Edit10.Text:=‘‘;Edit10.Color:=clWindow;Edit11.ReadOnly:=false;Edit11.Text:=‘‘;Edit11.Color:=clWindow;
Edit12.ReadOnly:=false;Edit12.Text:=‘‘;Edit12.Color:=clMenu;
Edit25.ReadOnly:=false;Edit25.Text:=‘‘;Edit25.Color:=clWindow;end;procedure Tinoutform.SpeedButton22Click(Sender: TObject);var s:integer;begin file://出库管理确定按钮事件
if(Edit24.Text=‘‘)or(Edit27.Text=‘‘)or(Edit28.Text=‘‘)then begin MessageDlg(‘请输入完整的出库信息!‘,mtInformation,[mbok],0);Edit24.SetFocus;end else begin if Edit27.Text>Edit21.Text file://检查出库数量是否小于库存数量 then begin MessageDlg(‘库存中的图书数量不够!‘,mtInformation,[mbok],0);Edit27.Text:=‘‘;Edit27.SetFocus;end else begin with datamoduleform.OutQuery do begin close;SQL.Clear;SQL.Add(‘insert into OutRecord values(:OutID,:BookID,:EmpID, :Number,:OutTime)‘);file://添加出库记录
Parameters.ParamByName(‘OutID‘).Value:=Edit23.Text;Parameters.ParamByName(‘BookID‘).Value:=Edit14.Text;Parameters.ParamByName(‘EmpID‘).Value:=Edit24.Text;Parameters.ParamByName(‘Number‘).Value:=Edit27.Text;Parameters.ParamByName(‘OutTime‘).Value:=Edit28.Text;execSQL;end;
第五篇:图书管理系统数据库设计
数据库设计.................................................................2 3.1 专门术语的定义...................................................2 3.1.1 系统中常用的术语(或使用频率较高的术语).........................2 3.1.2 表格定义及规范.................................................2 3.1.2.1数据约定.....................................................2 3.1.2.2表和表字段命名规范:.........................................3 3.2 数据设计.........................................................3 3.2.1 数据流程图设计.................................................3 3.2.2实体关系结构设计...............................................4 3.3安全保密设计.....................................................6 3.3.1 逻辑上的安全保密...............................................6 3.3.2 物理上的安全保密...............................................6 3.4 表格与功能模块相关性分析.........................................7 3.5 表格定义.........................................................7 数据库设计
3.1 专门术语的定义
暂无
3.1.1 系统中常用的术语(或使用频率较高的术语)暂无
3.1.2 表格定义及规范 3.1.2.1数据约定
所有数据项都用英文、汉语拼音或缩写表示,数据库名称除外。
所有字段在设计时,除以下数据类型timestamp、image、datetime、smalldatetime、uniqueidentifier、binary、sql_variant、binary、varbinary外,必须有默认值。字符型的默认值为一个空字符值串;数值型的默认值为数值0;逻辑型的默认值为数值0;
其中:系统中所有逻辑型中数值0表示为“假”;数值1表示为“真”。datetime、smalldatetime类型的字段没有默认值,必须为NULL。当字段定义为字符串形时建议使用varchar而不用nvarchar。建议在大多数表中(如报销单,申请单),应都有以下字段: 字段名说明类型默认值 CreatorID创建者int CreatedTime创建时间DatetimeNULL 字符集采用 UTF-8,请注意字符的转换。
所有数据表第一个字段都是系统内部使用自动序列主键列,自增字段,不可空,名称为:id,确保不把此字段暴露给最终用户。
除特别说明外,所有字符串字段都采用varchar(50)类型,(无论汉字还是英文,都算一个字符)。
除特别说明外,所有小数的字段都采用 decimal(18,2)的形式表达。
除特别说明外,所有日期格式都采用 datetime 格式(根据需要提取时间格式); 除特别说明外,所有整形都采用 bigint 格式。除特别说明外,所有字段默认都设置为 null。3.1.2.2表和表字段命名规范:
命名规则约束的范围包括:数据库的命名、表的命名及字段的命名。数据库相关的命名规则采用与通常的编程的变量命名规则原则一致,具体要求如下: 1)字段名及表名为典型的名词结构; 2)中文名称要求语言精练、文法严谨;
3)望文知意、易懂易用,禁止采用如:A002这种命名;
4)主体采用拼音字母的首写字母拼写构成,基于惯常法可适度采用无词义歧义性的英文命名;
5)长度不少于3个字母,不大于12个字母;
6)在对于拼音首字母类似的字段和表,为区别,添加下划线和数字如男性人数:NXRS,女性人数:NXRS_2。
3.2 数据设计
绘制数据流程图的目的是为了方便开发人员与用户的交流,以及为系统的设计提供依据。数据流程图的绘制过程通常采用自顶向下,逐层分解,直到功能细化为止,形成若干层次的数据流程图。3.2.1 数据流程图设计
0层数据流图
1层数据流图
3.2.2实体关系结构设计
图书实体关系
读者实体关系
图书借阅关系实体
用户实体关系
图书类别实体关系
3.3安全保密设计
3.3.1 逻辑上的安全保密
1、系统对非法使用者的安全保密处理措施
2、系统对正常使用者的安全保密处理措施
3、系统对管理员的安全保密 3.3.2 物理上的安全保密
1、数据库系统异常时的还原处理措施
2、设备遭异常毁坏时的安全防护措施
3、数据参数做到及时更新,保证系统正常运行
3.4 表格与功能模块相关性分析
3.5 表格定义
a.图书信息表
b.读者信息表
c.借阅表
d.管理员_书籍
e.管理员_学生