版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
局域网图书资料查询系统
除属性,就不是键了。3)主键:(PrimaryKey):用户选作元组标识的一个侯选键称为主键。一般,如不加说明,则键是指主键。3.关系的定义和性质我们可以用集合的观点定义关系。关系是一个元数为K(K>=1)的元组的集合。把关系看成是一个集合,集合中的元素是元组,每个元组的属性个数应相同。在关系模型中,对关系作了下列规范性限制:1)关系中每一个属性值都是不可分解的。2)关系中允许出现相同的元组(没有重复元组)3)由于关系是一个集合,因此不考虑元组间的顺序,即没有行序。4)元组中,属性在理论上也是无序的,但在使用时按习惯考虑列的顺序。2.1.2数据库的设计理论关系数据库的设计理论主要包括三个方面的内容:数据依赖、范式,模式设计方法。其中数据依赖起着核心的作用。1.函数依赖(Functionaldependency,FD)的定义设R(U)是一个关系模式,U是R的属性集合,X和Y是U的子集。对于R(U)的任何一个可能的关系r,如果r中不存在两个元组,它们在X上的属性值相同,而在Y上的属性值不同,则称“Y函数依赖于X”,记作X→Y。如果X→Y,并且对于X的任一真子集X’,都有Y不函数依赖于X’,则称“Y完全函数依赖于X”,记作XfY。若X→Y,但Y不完全函数依赖于X,则称“Y部分函数依赖于X”,记作XPY。如果X→Y,Y→Z,且Y≮X,X不函数依赖于Y,则称“Z传递函数依赖于X”。2.范式在对表的形式进行了规范化定义后,数据结构还有五种规范化定义,定名为规范化模式,称为范式。在这五种范式中,一般只用前三种,对于常用系统就足够了。而且这五种范式是“向上兼容”的,即满足第五范式的数据结构自动满足一、二、三、四范式,满足第四范式的数据结构自动满足第一、二、三范式,……,依此类推。第一范式(firstnormalform,简称1stNF)就是指在同一表中没有重复项出现,如果有则应将重复项去掉。这个去掉重复项的过程就称之为规范化处理。在本文所讨论的开发方法里,1stNF实际上是没有什么意义的。因为我们按规范化建立的指标体系和表的过程都自动保证了所有表都满足1stNF。第二范式(secondnormalform,简称2ndNF)是指每个表必须有一个(而且仅一个)数据元素为主关键字(primarykey),其它数据元素与主关键字一一对应。例如,在图l9.7中如果我们将合同号定义为主关键字(其它数据元素中的记录数据都有可能重名,故不能作为主关键字),故只要知道了一个合同记录的合同号,就可以唯一地在同一行中找到该合同的任何一项具体信息。通常我们称这种关系为函数依赖(functionaldepEndence)关系。即表中其它数据元素都依赖于主关键字,或称该数据元素唯一地被主关键字所标识。第三范式(thirdnormalform,简称3rdNF)就是指表中的所有数据元素不但要能够唯一地被主关键字所标识,而且它们之间还必须相互独立,不存在其它的函数关系。也就是说对于一个满足了2ndNF的数据结构来说,表中有可能存在某些数据元素依赖于其它非关键宇数据元素的现象,必须加以消除。为防止数据库出现更新异常、插入异常、删除异常、数据冗余太大等现象,关系型数据库要尽量按关系规范化要求进行数据库设计。下面以教务管理信息系统为例来进行分析。3.模式设计方法一个好的模式设计方法应符合下列三条原则:l表达性:涉及到两个数据库模式的等价性问题,即数据等价和依赖等价,分别用无损联接和保持函数依赖来衡量。l分离性:是指属性间的“独立关系”应该用不同的关系模式表达。独立联系是我们所考虑的“基本信息单位”。实际上分离就是清除存储异常和数据冗余现象。如果能达到这个目的,就分离。分离的基准就是一系列范式,分离与依赖等价有时是不可兼容的。l最小冗余性:要求在分解后的数据库能表达原来数据库的所有信息这个前提下实现。目的就是节省存储空间,提高对关系的操作效率,清除不必要的冗余。但要注意,在实际使用中,并不一定要达到最小宙余。因为有时带点冗余对于查询处理是有好处的。关系模式的方法基本上可以分为分解与合成两大类。分解型算法要求输入一个初始模式集和依赖集,而结果满足数据等价要求。对于合成型算法只要求输入初始依赖集,结果满足依赖等要求。但它们依据的基本思想是共同的,即独立的联系独立表示。§2.2SQL语言介绍SQL(StructuredQueryLanguage)即“结构式查询语言”。SQL虽然名为查询语言,但实际上具有定义、查询、更新和控制等多种功能。由于它使用方便、功能丰富、语言简单易学,很快得到应用和推广。从20世纪70年代末起,在推出的关系数据库系统产品ORACLE、SQL/DS、DB2、SYBASE上实现了SQL语言。很快,SQL语言被整个计算机界认可。1987年6月,国际标准化组织(ISO)采纳为国际标准。随后,ISO对标准进行了大量的修改和扩充。在1992年推出了新的标准-SQL2。SQL的标准化工作还在继续,新的标准已被命名为SQL3,将包括许多新的数据库概念,正在不征求意见和进行修改这里将简单介绍基于SQL89和SQL2的语言使用概貌:2.2.1SQL的组成SQL主要分成四个部分:1)数据定义:这一部分也称为“SQLDDL”,用于定义SQL模式、基本表、视图和索引。2)数据操纵:这一部分也称为“SQLDML”。它分为数据查询和数据更新两类。其中数据更新又分成插入、删除、和修改三种操作。3)数据控制:这一部分包括对基本表和视图的授权,完整性规则的描述,事务控制等内容。4)嵌入式SQL的使用规定:这一部分内容涉及到SQL语句嵌入在宿主语言程序中使用的规则。2.2.2SQL的数据查询nSELECT语句的语法SELECT目标表的列名或列表达式序列FROM基本表和(或)视图序列[WHERE行条件表达式][GROUPBY列名序列[HAVING组条件表达式]][ORDERBY列名[ASC|DESC]…]句法中[]表示该成分可有,也可无。整个语句的执行过程如下:a)读取FROM子句中基本表、视图的数据,执行笛卡尔积操作。b)读取满足WHERE子句中给出的条件表达式的元组。c)按GROUP子句中指定列的值分组,同时提取满足HAVING子句中组条件表达式的那些组。d)按SELECT子句中给出的列名或列表达式求值输出。e)ORDER子句对输出的目标表进行排序,按附加说明ASC升序排列,或按DESC降序排列。SELECT语句中,WHERE子句称为“行条件子句”,GROUP子句称为“分组子句”,HAVING子句称为“组条件子句”,ORDER子句称为“排序子句”。2.2.3SQL的数据更新SQL的数据更新包括数据插入、删除和修改等三种操作1)数据插入a)元组值的插入INSERTINTO基本表名(列名表)VALUES(元组值)或者INSERTINTO基本表名(列名表)(TABLE(元组值),(元组值),……)前一种格式只能插入一个元组,后一种格式可以插入多个元组。2)数据删除SQL的删除操作是指从基本表删除元组,其语法如下:DELETEFROM基本表名[WHERE条件表达式]其语义是从基本表中删除满足条件表达式的元组。3)数据修改当需要修改基本表中元组的某些列值时,可以用UPDATE语句实现,其句法如下:UPDATE基本表名SET列名=值表达式[,列名=值表达式…][WHERE条件表达式]其语义是:修改基本表中满足条件表达式的那些元组中的列值,需修改的列值在SET子句中指出。§2.3PB6.5对数据库的操作PowerBuilder对数据库的操作即可以通过数据窗口完成(本质上是数据窗口把在屏幕上对数据库的操作转化成SQL语句),又可以在PowerScript语言中直接调用SQL或存储过程(本质上仍是SQL语句)完成。下面通过列举两个简单实例来描述在PowerScript程序调用SQL的方式:1、SELECT语句查询返回一行如果SQLSELECT语句返回的结果只有一行,可以在PowerScript中书写以下的SQL语句:SELECT列名1,列名2,列名3,…INTO:变量1,:变量2,:变量3…FROM表名1,表名2,表名3,…WHERE…其中,“变量1”,“变量2”和“变量3”等都是PowerScript语言的变量。该语句的作用是把数据库表的“列名1”,“列名2”和“列名3”等列的值从数据库中取出,然后放入对应的“变量1”,“变量2”和“变量3”等变量中。例如:Stringname,extraceSELECTname,extractINTO:name,:extracefromauths
Whereauthor_code=’A00001’;该语句仅仅适合于查询到一条记录的情况。如果查询到的记录是多条,则要用下面的方法。2、查询多行SELECT是描述型语言,它面向的是集合,是一组记录。而PowerScript语言却是面向过程的,它要一条条地接收并处理记录。PowerScript通过描述型光标(CURSOR)在这组记录上游动的方法,给Script语句逐个地传送记录,建立了集合与记录间的内在联系。请看下例:StringnameStringV1=’A%’
DECLARECURSORFORfile://定义光标,光标名为C1SELECTnameFROMauths
file://光标对应的SELECT语句WHEREauthor_codelike:V1;file://SELECT语句中用到了变量V1
OPENC1;//打开光标,此时执行此光标对应的SQLSELECT语句。
Lab1:
FETCHC1INTO:name;
file://取记录,光标下移一条
IfSQLCA.SQLCode=0thenfile://取记录成功
Gotolab1file://如果成功取出记录,则取下一条
Endif打开光标的时候,变量V1被其值“A%”替换,因此最后执行的SQLSELECT语句为:SELECTnameFROMauthsWHEREauthor_codelike‘A%’执行完这条语句后,把光标C1定位到了查询出的第一条记录上。每执行一次语句:FECTCHC1INTO:name;则取出一条记录送给变量name,然后光标移到下一条记录。如果想控制查询结果的次序,必须在SELECT语句中用ORDERBY子句,否则,没有其它的办法。我们不可能一下子把光标定位在某条记录上,只能从第一条开始,一个个地移。第三章PB6.5及其数据库编程§3.1开发工具PowerBuilderPowerBuilder6.5特点及功能要适应企业环境不断变化的需求,成功地开发出高质量的应用系统,必须采用先进的应用开发工具。这对于减轻应用开发人员的开发负担,提高开发速度和质量都有十分重要的意义。Sybase公司推出的PowerBUilder6.0/6.5是用于Client/Server、Web及组件开发的企业级应用开发工具。它占全球开发工具市场近50%,是当前最优秀的开发工具之一。它具有以下优异的功能和特点:1、内置的关系数据库PowerBuilder本身带有一套数据库系统SybaseSQLAnywhere。这样做的好处是,PowerBuilder可以脱离网络数据库服务器独立运行,从而在开发阶段脱离网络服务器上的数据库。当然,利用这一功能也可以开发和调试单用户的独立的数据库应用。下图显示了内置数据库的工作原理:如果没有内置的数据库SybaseSQLAnywhere,开发时则不能脱离网络服务器上的数据库(如图3-2所示):2、数据窗口(Datawindow)对象PowerBuilder拥有数据窗口这个具有专利技术的智能对象,利用该对象可以操作关系数据库的数据而无需编写SQL语句。用户可以查询、修改、插入、删除、浏览、打印、以多种文件格式打开和存储数据,或在数据窗口中直接定义功能按钮实现预定义的系统功能,如插入、删除数据的操作。它还支持数据库事务管理和并发控制等机制。其工作机理如下图所示:3、丰富的数据窗口数据源和多种样式的数据显示格式数据窗口可以用来维护数据和显示数据,可定义多种显示风格和数据显示格式;并且还可以与TreeView控制、ListView控制配合使用,创建出更丰富的数据显示格式4、支持多种商业图形,包括多种类型的二维和三维的图形5、支持组件的开发和调用用PowerBuilder开发的组件,可以在其它应用中调用,可以由多种事务管理服务器管理。6、具有面向对象的特征PowerBuilder采用了面向对象的开方式,这可以使系统开发人员在无需精通专用语言的情况下就可以迅速转向面向对象的开发。PowerBuilder应用是由一系列对象组成的,包括窗口、菜单、函数、数据窗口和各种控制等对象,它支持对象的继承、封装和多态性。7、有机结合的集成开发环境8、完全支持Windows的窗口信息和控制9、强有力的PowerScript编程语言它能使开发人员很容易地将简单或复杂的事务逻辑与应用相配合。该语言还有几百个函数用于操纵对象、处理数字、文本、字符串、日期和应用分布,进行文件处理、报表打印,用DDE和OLE2.0进行程序之间的通信,直接调用SQL语句操纵数据库等等。10、PowerBuilder提供了多种流行软件的接口库NetwareLibraryPenComputingLibraryLotusNotesLibraryMicrosoftMAPI11、PowerBuilder支持多种平台目前,PowerBuilder能够在MicrosoftWindows3.X、Windows95WindowsNTAlpha/IntelAppleMacSunSalorisIBMAIXHPUnix等多种平台上开发和运行应用程序,并能够不加改动地应用于其它平台上。12、支持Internet/Intranet下的Web应用开发13、支持团体开发14、对多种数据库的支持PowerBuilder几乎支持所有的数据库,它提供了到多种数据库的专用接口和ODBC接口。§3.2PowerBuilder与Client/Server体系结构3.2.1Client/Server模式在C/S结构中,存在着几个非常重要的基本概念,它们是:主机、终端、客户机、工作站和服务器。在分析C/S网络结构之前,必须搞清楚它们之间的区别。最早的计算机网络是伴随着主机(Host)和终端(Terminal)这两个概念的出现而产生的。当时的主机通常是指具有中央处理单元(CPU)的大型机或功能较强的小型机,而终端则是指计算机的输入输出设备。终端没有自己的CPU,当然也没有自己的内存,其主要功能是将键盘输入的请求数据发往主机并将主机的运算结果显示出来。主机和终端共同构成了集中式系统结构。在这种应用系统中,几乎所有的工作都是由主机来完成,终端仅仅作为一种输入输出设备,因此系统负荷重、效率低、扩充性差。之后随着计算机网络结构的细化,不同的计算机开始在网络中担负不同的任务,于是出现了文件服务器/网络工作站(F/W)式结构的模型。其中,工作站(Workstation)和服务器(Server)都是独立的计算机。当一台连入网络的计算机向其它计算机(工作站)提供各种网络服务(如数据、文件的共享)时,它就被叫做服务器。而那些用于访问服务器资料的计算机则被叫做工作站。在F/W结构中,所有实际的数据处理工作仍在运行数据库应用程序的PC工作站上完成,因此不论文件服务器的性能有多高,其整体网络性能都将受到PC机能力的限制。客户机(Client)是伴随C/S数据访问的兴起而被提出来的,在一般人的理解中它和F/W概念没有本质的区别。但是,严格说来,C/S模型并不是从物理分布的角度来定义的。它既包括具体的网络结构设计,又包括软件的运行和组织,所体现的是一种网络数据的访问方式。这里的客户机和服务器不仅指承担不同任务的计算机本身,而且包括主机上运行的客户端和服务器端的软件环境。它们的区别,是相对于各自在网络数据库访问中所处的地位或实现的功能而言的。理解了以上的基本概念,才可以更好地理解C/S结构的实质和运行方式:所谓C/S结构,是将数据存取与应用程序分离开来,把一个软件系统或应用系统按功能分成若干个部分,再将这些软件的组成部分按其不同的角色分成Client软件和Server软件,分别放置在客户机和服务器上。客户机程序负责用户交互界面、数据表示及应用处理逻辑等应用部分,而服务器端则负责数据存取管理、完整性控制及并发控制等数据库管理部分。客户机程序应用通过SQL语句访问数据库,相应的SQL语句经网络传输到服务器端,由服务器端的数据库服务器解释执行这些SQL语句,执行后的结果数据送回客户机。来承担,服务器的能力可以得到充分的发挥。但是它也有以下一些缺点:l由于计算机技术的快速进步和企业需求变化的加快,企业面临的硬件、网络操作系统、数据库系统、开发工具、应用系统的升级周期越来越短,因此“维护”客户服务器的费用就变得越来越高昂。l快速升级的硬件、网络操作系统、数据库系统、开发工具使企业的技术人员失去了方向:不断地消化新技术,却无瑕顾及企业要解决的问题l在客户端,必须安装操作系统(一般为Windows95/NT)、网络软件、特定的中间件(SybasseNet-Library)以及应用软件系统才能工作,因此应用系统的安装、升级和维护通常需要专业人员才能用胜任,且必须各站点逐个安装,从而使客户端的维护费用变得也很高昂。对主机系统来说,这一点要优越的多,只需要在主机上安装一次即可。3.2.3PowerBuilder是客户/服务器体系结构下客户端的开发工具前面已提到,PowerBuilder是客户/服务器体系结构下开发客户程序用的开发工具,用PowerBuilder开发出的程序可以存取数据库中的数据。下图表示了PowerBuilder与数据库配合工作的方式。我们看到,PowerBuilder作为客户端的应用开发工具,主要完成的是表示逻辑方面的工作,例如,菜单、录入界面。而数据库服务器管理的是事务逻辑和数据存取方面的工作。因此,PowerBuilder开发工作应分为两部分,一部分是前台表示逻辑方面的工作,另一部分是数据库后台方面的设计工作(如数据库触发器、存储过程和视图等的设计)。一个好的应用系统,前台开发与后设计应是有机结合、合理分布的;良好的后台设计可以降低前台的开工作量,提高系统的运行效率。§3.3PowerBuilder6.5数据库编程PowerBuilder与数据库的关系是“配合”与“协调”的关系。PowerBuilder完成数据请求、数据表现、菜单、界面等表象方面的工作,而数据库服务器完成数据库数据的存储管理、安全管理、并发控制、事务管理、完整性维护、查询优化等工作。PowerBuilder在操作数据库时与以下几方面有关:1、在数据库画笔中定义数据库表和视图l定义表的结构l表中列的扩展属性²定义表中列的显示风格²定义表中列的编辑屏蔽²定义表中列的校验l定义表的主键l定义表的外部键l定义表的索引PowerBuilder有五个系统表,这五个系统表是PowerBuilder初次连接到数据库时系统自动建立的。下表给出了这个系统表的表名和它们的作用PowerBuilder系统表用途PBCATTBL存放表或视图,表或视图中列的缺省字体。PBCATCOL存放列用到的显示风格名、校验规则名和编辑风格名;列的标题、列的标签、字体的大小写,字体的对齐方式。PBCATFMT列的显示风格定义。PBCATVLD列的校验规则定义。PBCATEDT列的编辑风格定义。表3-1PowerBuilder系统表2、在数据库画笔中在图形方式下操作数据库这些操作包括:l插入记录l修改记录l删除记录l查询记录l把查询出的记录存入文件l把表或视图的定义转变成建表的SQL语名这些功能是给开发人员和管理人员提供的。3、在数据库画笔中用SQL语句执行平台管理操作数据库l生成数据库l管理数据库l维护数据在这里创建的表和规则不会记录在PowerBuilder系统表中4、在查询画笔中定义查询对象如果一个查询动作要多次使用,还可以用PowerBuilder的查询画表生成查询对象这个查询对象不能由数据库画表调用,它只能由查询画表本身调用执行。在建立数据窗口时,数据源也可以做在查询对象之上。事实上,查询对象就是写好了的SQL语句,它存在PowerBuilder的pbl文件中,在使用的时候调用即可。5、用数据管道在不同数据库之间转换数据数据管道允许把一个数据库的数据(一个或多个表中的全部或部分行)转入到另一个数据库的一个表中(这个表可以存在或不存在),从而可以使数据在不同数据库之间相互复制。6、用数据窗口操作数据库Datawindow是PowerBuilder操作数据库的重要的手段,通过数据窗口可以查修改、插入和删除数据库的数据。PowerBuilder数据窗口操作数据库的能力非常强,是PowerBuilder的精华所在。l数据窗口的数据源可以是:²表或视图²多表连接²查询对象²外部数据源²存储过程l数据窗口列数据的显示风格l数据窗口列的编辑屏蔽l数据窗口列的校验7、PowerScript直接调用SQL语句操作数据库PowerBuilder对数据库的操作即可以通过数据窗口完成(本质上是数据窗口屏幕上对数据库的操作转化成SQL语句),又可以在PowerScript语言中直接调用SQL或存储过程(本质上仍是SQL语句)完成。详细操作在第*个章节已经介绍。第四章局域网图书资料查询系统设计分析根据数据库系统生存期的设计方法,从数据库应用系统和开发的全过程来考虑,将数据库应用系统设计分为以下几个阶段(见图4-1)1)规划;2)需求分析;3)概念设计;4)逻辑设计5)物理设计§4.1应用需求分析要设计一个良好的局域网图书资料查询系统,就必须首先明确该应用环境对系统的要求。局域网图书资料查询系统的应用背景为:一个数十人的科研或开发小组,搜集了上千册有用的图书资料,其中有一部分分布在个人手中,为了方便大家查阅,需要对每本书的状态进行跟踪,另新进和丢失的图书资料必须得到及时的反映。因此,该系统需满足以下几方面需求:l用户的管理:必须具有使用权限的用户才能成功登录到系统中来。所谓用户权限在这里并不要求有功能上具体的划分,集中实行松散管理,这建立在用户高度自觉的基础上。所以,在这里只需给每个需要使用系统的人一个用户名和密码,即可登录系统进行各种操作。新的用户需要取得管理员的许可将其加入系统,加入系统的用户可以对自己的用户密码进行修改。l查询功能:系统需要提供几种不同方式的查询手段,以实现灵活方便地管理整个系统。²图书分类查询:一本图书包括书名、出版社、作者、保管人等多个信息,这就要求系统能按照不同的信息类别对图书进行查询。比如说,按书名查询、按作者查询等。选定需要的查询信息类别,再输入想查询的内容即可查询到相关的图书信息。²多条件查询:很多时候,用户需要了解的信息不仅仅局限于一个条件,比方说想同时查询书名为“数据库原理”但出版社仅为“经济科学出版社”的图书信息时,单纯的分类查询就不能满足用户的需要,这时就要用到多条件查询。也就是说,多条件查询不仅可以实现单个的分类查询,还可以实现多条分类查询的组合查询。每个查询条件之间用“并且”或“或者”的关系关联起来组成完整的查询条件。²模糊查询:对于用户来说并不一定完全记得某本图书准确的名称,类似,对于作者、出版社等等信息来说,很多时候用户只是记得一些相关的信息而不是一字不差的准确信息。这个时候就要用到模糊查询。用户输入查询内容后,系统将会把包含查询内容的(注意:并不是精确的等于查询内容)所有相关图书信息显示出来,以使用户得到准确的、自己真正需要的信息内容。l更新与编辑:²更新:系统允许用户对查询到的内容进行修改并且存盘。²编辑:系统允许用户对现库进行插入、删除的操作,保证现库的真实性与实时性。l打印输出:系统可以将用户查询到的内容动态地生成报表,并打印输出。§4.2系统功能模块划分局域网图书图书资料查询系统功能划分模块图如下:§4.3系统数据库设计4.3.1概念设计概念设计的目标是产生反映局域网图书资料查询系统需求的数据库概念结构,即概念模式。概念模式是独立于数据库逻辑结构,独立于支持数据库的DBMS,不依赖于计算机系统的。lER模型ER模型是对现实世界的一种抽象。它的主要成分是实体、联系和属性。使用这三种成分,我们可以建立许多应用环境的ER模型。lER模型的操作在利用ER模型进行数据库概念设计的过程中,常常需要对ER图进行种种变换。这些变换又称为ER模型的操作,包括实体类型、联系类型和属性的分裂、合并和增删等等。l利用ER方法的数据库概念设计利用ER方法进行数据库的概念设计,可以分成三步进行:首先设计局部ER
模式,然后把各局部ER模式综合成一个全局ER模式,最后对全局ER模式进行优化,得到最终的ER模式,即概念模式。
1.设计局部的ER模式通常,一个数据库系统都是为多个不同用户服务的。各个用户对数据的观点可能不一样,信息处理需求也可能不同。在设计数据库概念结构时,为了更好地模拟现实世界,一个有效的策略是“分而治之”,即先分别考虑各个用户的信息需求,形成局部概念结构,然后再综合成全局结构。在ER方法中,局部概念结构又称为局部ER模式,其图形表示称为ER图。实体和属性的定义如下:图书(资料编号,资料名称,作者,出版社,出版日期,ISBN,资料类别,购买日期,保管人,备注)用户(编号,用户代码,用户姓名,登录口令,使用权限,查询显示项,用户显示头像)资料类别(资料编号,资料类别)出版社(出版社编号,出版社),依据需求分析的结果,考察局部结构中任意两个实体类型之间是否存在联系。若有联系,进一步确定是1:N,M:N,还是1:1等。还要考察一个实体类型内部是否存在联系,两个实体类型之间是否存在联系,多个实体类型之间是否存在联系,等等。联系定义如图4-5所示。解释如下:l一个用户可以保管多本图书资料,而一本图书资料只能由一个用户保管;l一个资料类别可以对应多本图书,而一本图书只对应一个资料类别;l一本图书由一个出版社出版,而一个出版社可以出版多种图书。3.设计全局ER模式所有局部ER模式都设计好了后,接下来就是把它们综合成单一的全局概念结构。全局概念结构不仅要支持所有局部ER模式,而且必须合理地表示一个完整、一致的数据库概念结构。1)确定公共实体类型为了给多个局部ER模式的合并提供开始合并的基础,首先要确定各局部结构中的公共实体类型。在这一步中我们仅根据实体类型名和键枕认定公共实体类型。一般把同名实体类型作为公共实体类型的一类候选,把具有相同键的实体类型作为公共实体类型的另一类候选。2)局部ER模式的合并合并的原则是:首先进行两两合并;先和合并那些现实世界中有联系的局部结构;合并从公共实体类型开始,最后再加入独立的局部结构。3)消除冲突冲突分为三类:属性冲突、结构冲突、命名冲突。设计全局ER模式的目的不在于把若干局部ER模式形式上合并为一个ER模式,而在于消除冲突,使之成为能够被所有用户共同理解和接受的同一的概念模型。3)全局ER模式的优化在得到全局ER模式后,为了提高数据库系统的效率,还应进一步依据处理需求对ER模式进行优化。一个好的全局ER模式,除能准确、全面地反映用户功能需求外,还应满足下列条件:实体类型的个数要尽可能的少;实体类型所含属性个数尽可能少;实体类型间联系无冗余。4.3.2逻辑设计由于概念设计的结果是ER图,DBMS一般采用关系型,因此数据库的逻辑设计过程就是把ER图转化为关系模式的过程。由于关系模型古有的优点,逻辑设计可以充分运用关系数据库规范化理论,使设计过程形式化地进行。设计结果是一组关系模式的定义。1)导出初始关系模式图4-5关系模式集
2)关系子模式子模式是用户所用到的那部分数据的描述。除了指出用户用到的数据外,还应指出数据与概念模式中相应数据的联系,即指出概念模式与子模式之间的对应性。图书信息子模式((编号#,资料名称,作者,出版社,出版日期,ISBN,资料类别,购买日期,保管人,备注)用户信息子模式(编号,用户代码,用户姓名,登录口令,使用权限,查询显示项,用户显示头像)图4-6部分子模式4.3.3数据库的实现我们选用MicrosoftOffice中的Access数据库来进行数据库的逻辑设计。首先创建四个基本数据库表如如4-1-4-5所示,然后建立各个表之间的联系,如图4-8所示。第五章局域图书资料查询系统应用程序设计§5.1系统模块组成§5.2登录模块实现图5-2登录模块图
该窗口所含的控件信息如下:风格控件名说明用户名SinglelineeditSle_1
口令SinglelineeditSle_1Propeties:passwd登录日期EditMaskEm_1masktype:datamm/dd/yyyy表5-1登录模块控件信息表控件:Sle_1
事件(event):Modified
Scriptofmodified:stringinput_code,namesetfocus()file://将光标定位在该控件input_code=string(this.text)file://接收用户输入的值,并赋值给变量selectnameinto:namefromkeeperwhereid=:input_codeorpym=:input_code;//从用户表里查找满足输入条件的记录ifsqlca.sqlcode=0thenthis.Text=namesetfocus(sle_2)file://查找成功,则光标跳转到“口令”控件elseifsqlca.sqlcode=100thenmessagebox("提示!",&"对不起,用户不存在!",&
StopSign!)return1file://查找不到符合条件的记录则提示elsemessagebox("错误!",&"error:"+string(sqlca.sqldbcode)&+"information:"+sqlca.sqlerrtext)file://SQL出错提示endifendif控件:Sle_2
事件(event):Modified
Scriptofmodified:stringinput_passwd,passwd,droitinput_passwd=RightTrim(this.text)//去掉输入值右边的空格selectpasswdinto:passwdfromkeeperwherename=:sle_1.text;passwd=RightTrim(passwd);//从用户表中校验口令的正确性ifsqlca.sqlcode=0thenifinput_passwd<>passwdthen
messagebox('口令错误','对不起,请重新输入',stopsign!);
sle_2.SelectText(1,Len(sle_2.Text))
this.Clear()//口令错误则清除输入内容
setfocus(sle_2)elseifinput_passwd=passwdthenuser=righttrim(sle_1.text)selectdroitinto:droit
fromkeeper
wherename=:user;//口令正确将用户操作权限赋值给变量open(main)//打开程序主窗口
close(w_login)//关闭登录窗口endifelseifsqlca.sqlcode=100thenmessagebox('提示!','无数据',Stopsign!)return1elsemessagebox("错误!",&"error:"+string(sqlca.sqldbcode)&+"information:"+sqlca.sqlerrtext)file://SQL出错提示endif在登录模块中,用户可输入自己的编号或编码来登录系统。系统会根据用户输入的编号或编码值来自动给出确实已存在库中的用户中文名,若查找不到库中相匹配的记录则提示出错或重输。若用户存在,则提示输入口令,口令正确则会顺利进入该系统主界面。更新打印Datawindowscontroldw_1对应数据窗口d_information图书信息检索Datawindowscontroldw_2对应数据窗口d_query_condition查询条件检索CommandbuttonCb_2模糊查询操作符英-中转换表5-2查询模块控件信息表控件:w_main
事件(event):open
Scriptofopenstringmode,p,xs,headbooleanxs_item[10]integeridw_1.settransobject(sqlca)dw_1.Retrieve()//打开窗口显示全部记录sj_check=0//为检索窗口排序变量赋初值st_1.text=user//在查询窗口右上角显示当前用户名SELECT"keeper"."display_item","keeper"."head_picture"INTO:xs,:headFROM"keeper"WHERE"keeper"."name"=:user;//从用户表中读出当前用户的头像值及显示像值并分别赋值给变量file://有头像的用户则显示在查询窗口右上角ifisnull(head)thenp_3.visible=falseelsep_3.picturename=headendif////将当前用户查询显示项变量读出并赋值给每个查询显示控件fori=1to8ifMid(xs,i,1)='0'thenxs_item[i]=falseelsexs_item[i]=trueendifendfor////给每个对应的CHECKBOX赋值,确实是勾还是叉cbx_2.checked=xs_item[1]cbx_3.checked=xs_item[2]cbx_4.checked=xs_item[3]cbx_5.checked=xs_item[4]cbx_6.checked=xs_item[5]cbx_7.checked=xs_item[6]cbx_8.checked=xs_item[7]cbx_9.checked=xs_item[8]////对应的数据窗口显示情况dw_1.object.id.visible=falsedw_1..visible=truedw_1.object.author.visible=cbx_2.checkeddw_1.object.publishing_house.visible=cbx_3.checkeddw_1.object.publishing_date.visible=cbx_4.checkeddw_1.object.sort.visible=cbx_5.checkeddw_1.object.buy_date.visible=cbx_6.checkeddw_1.object.isbn.visible=cbx_7.checkeddw_1.object.keeper.visible=cbx_8.checkeddw_1.object.memo.visible=cbx_9.checked////将查询数据窗口设为只读dw_1.Object.DataWindow.ReadOnly="Yes"控件:pb_12“存为默认显示选项”事件(event):clicked
Scriptofclickedbooleancheck[10]integeri,answerstringxs_item[10]stringxs_content,question_text,tempquestion_text="将当前显示项存为"+user+"用户的默认显示项?"answer=messagebox('提示!',question_text,question!,YesNoCancel!)choosecaseanswercase1file://将当前对应的CHECEKBOX选项记录下来check[1]=cbx_2.checked
check[2]=cbx_3.checked
check[3]=cbx_4.checked
check[4]=cbx_5.checked
check[5]=cbx_6.checked
check[6]=cbx_7.checked
check[7]=cbx_8.checked
check[8]=cbx_9.checked//file://将显示项转化为01的显示,存入数组变量
xs_content=''fori=1to8ifcheck[i]=truethenxs_item[i]='1'else
xs_item[i]='0'endifxs_content=xs_content+xs_item[i]endfor//
file://修改用户表中显示项的值
UPDATE"keeper"SET"display_item"=:xs_contentWHERE"keeper"."name"=:user;
choosecaseSQLCA.sqlcodecase-1messagebox("错误!","error:"+&
string(sqlca.sqldbcode)+&
"information:"+sqlca.sqlerrtext)messagebox('提示','修改成功!')
commit;case100messagebox('!','修改失败!')
endchoosecase2returncase3returnendchoose5.3.1模糊(分类)查询的实现图5-4模糊查询窗口控件:ddlb_1事件(selectionchanged):
ScriptofSelectionchangedfile://清空历史查询内容em_1.selecttext(1,len(em_1.text))em_1.clear()sle_1.selecttext(1,len(sle_1.text))sle_1.clear()//运算符随查询内容的改变而改变ifddlb_1.text='出版日期'orddlb_1.text='购买日期'thenddlb_2.deleteitem(ddlb_2.FindItem("包含",2))ddlb_2.deleteitem(ddlb_2.FindItem("不包含",2))ddlb_2.deleteitem(ddlb_2.FindItem("小于等于",2))ddlb_2.deleteitem(ddlb_2.FindItem("大于等于",2))ddlb_2.insertitem('小于',3)ddlb_2.insertitem('大于',4)ddlb_2.insertitem('小于等于',5)ddlb_2.insertitem('大于等于',6)em_1.TextColor=RGB(255,0,0)sle_1.visible=Falseem_1.SetMask(DateMask!,'mm/dd/yyyy')elseddlb_2.deleteitem(ddlb_2.FindItem("小于",2))ddlb_2.deleteitem(ddlb_2.FindItem("大于",2))ddlb_2.deleteitem(ddlb_2.FindItem("小于等于",2))ddlb_2.deleteitem(ddlb_2.FindItem("大于等于",2))ddlb_2.deleteitem(ddlb_2.FindItem("包含",2))ddlb_2.deleteitem(ddlb_2.FindItem("不包含",2))ddlb_2.insertitem('包含',3)ddlb_2.insertitem('不包含',4)sle_1.visible=Truesle_1.TextColor=RGB(255,0,0)endif不可见控件:cb_2“转换”事件(event):Clicked
ScriptofClickedfile://将查询项转换为表info中字段名choosecaseddlb_1.textcase'资料名称'query_item='name'case'作者'query_item='author'case'出版社'query_item='publishing_house'case'出版日期'query_item='publishing_date'case'ISBN'query_item='ISBN'case'资料类别'query_item='sort'case'购买日期'query_item='buy_date'case'保管人'query_item='keeper'case'备注'query_item='memo'endchoose//将操作符转换为中文显示choosecaseddlb_2.textcase'等于'query_operator='='case'包含'query_operator='like'case'不等于'query_operator='<>'case'不包含'query_operator='notlike'case'小于等于'query_operator='<='case'大于等于'query_operator='>='case'小于'query_operator='<'case'大于'query_operator='>'endchoose控件:pb_1“检索”事件(event):Clicked
ScriptofClickedstringrqdatedcb_2.TriggerEvent(clicked!)//将英文操作符转换为中文显示dw_1.setredraw(true)old_sql=dw_1.getsqlselect()//得到原有数据窗口的SQL语句ifddlb_1.text='出版日期'orddlb_1.text='购买日期'then//查询项为日期类型em_1.GetData(d)//取出输入的日期数据rq=String(d,"yyyy/mm/dd")//将输入的日期数据转换为字符型choosecasequery_operator//根据操作符的不同将新产生的WHERE条件与老的SQL语句拼接成新的SQL语句case'='new_sql=old_sql+"where"+query_item&+""+query_operator+'date'+'('+"'"+rq+"'"+')'
case'<>'new_sql=old_sql+"where"+query_item&+""+query_operator+'date'+'('+"'"+rq+"'"+')'&+'or'+query_item+'isnull'case'<='new_sql=old_sql+"where"+query_item&+""+query_operator+'date'+'('+"'"+rq+"'"+')'case'>='new_sql=old_sql+"where"+query_item&+""+query_operator+'date'+'('+"'"+rq+"'"+')'endchoose////查询项为字符型elsesle_1.text=Righttrim(sle_1.text)//将当前输入内容右面的空格去掉choosecasequery_operator//根据操作符的不同将新产生的WHERE条件与老的SQL语句拼接成新的SQL语句
case'='new_sql=old_sql+"where"+query_item&+""+query_operator+"'"+parent.sle_1.text+"'"
case'<>'
new_sql=old_sql+"where"+query_item&
+""+query_operator+"'"+parent.sle_1.text+"'"&
+'or'+query_item+'isnull'case'like'new_sql=old_sql+"where"+query_item&
+""+query_operator+"'"+'%'+parent.sle_1.text+'%'+"'"case'notlike'new_sql=old_sql+"where"+query_item&
+""+query_operator+"'"+'%'+parent.sle_1.text+'%'+"'"&+'or'+query_item+'isnull'endchoose//endif//对原有数据窗口进行新的查询ifdw_1.setsqlselect(new_sql)=-1thenbeep(3)
messagebox("警告","检索失败",stopsign!)elsedw_1.settransobject(sqlca)
dw_1.retrieve()dw_1.setsqlselect(old_sql)endif5.3.2组合查询(条件查询)模块的实现:case'column_name'item=dw_2.getitemstring(dw_2.getrow(),'column_name')//根据查询项目改变操作符的显示Ifitem='publishing_date'oritem='buy_date'thendw_2.setrow(dw_2.getrow())dw_2.setitem(row,'content','')dw_2.setvalue('operator',1,'等于~t=')dw_2.setvalue('operator',2,'不等于~t<>')dw_2.setvalue('operator',3,'小于~t<')dw_2.setvalue('operator',4,'大于~t>')dw_2.SetValue('operator',5,'小于等于~t<=')dw_2.SetValue('operator',6,'大于等于~t>=')Status=dw_2.GetValue('operator',4)elsedw_2.setrow(dw_2.getrow())dw_2.setitem(row,'content','')dw_2.setvalue('operator',1,'等于~t=')dw_2.setvalue('operator',2,'不等于~t<>')dw_2.SetValue('operator',3,'包含~tlike')
dw_2.SetValue('operator',4,'不包含~tnot')
Status=dw_2.GetValue('operator',4)endif//case'operator'//防止操作符的显示改变operator1=dw_2.getitemstring(dw_2.getrow(),'operator')choosecaseoperator1case'like'dw_2.setitem(dw_2.getrow(),'operator','包含')case'not'dw_2.setitem(dw_2.getrow(),'operator','不包含')endchooseendchoose控件:pb_2“插入”事件(event):Clicked
ScriptofClickedintrow,new_row,istringqueryrow=dw_2.getrow()//将当前行的行号赋值给变量//允许插入一行的条件if(isnull(dw_2.getitemstring(row,'column_name'))or&
isnull(dw_2.getitemstring(row,'operator'))or&isnull(dw_2.getitemstring(row,'content'))or&isnull(dw_2.getitemstring(row,'join')))thenquery='no'elsequery='yes'endif//如果允许插入,则在当前行后插入一条新记录ifquery='yes'thennew_row=dw_2.insertrow(0)////将光标定位在新的一行“资料名称”列dw_2.scrolltorow(new_row)dw_2.setrow(new_row)dw_2.setcolumn(1)//elsemessagebox('警告',"请输入完整的查询条件",stopsign!)endif控件:pb_3“删除”事件(event):Clicked
ScriptofClickedintrow//如果当前行不为第一行,则允许删除ifdw_2.getrow()<>1thenrow=dw_2.getrow()//将当前行行号赋值给变量dw_2.deleterow(row)//删除当前行elsereturnendif控件:pb_4“检索”事件(event):Clicked
ScriptofClickedLongrow_count,rowstringnew_condition,itemstringcondition[100],column_name,operator,content,join,operator1inti//将当前行行号赋值给变量row=dw_2.getrow()//将当前行列名赋值给变量column_name=dw_2.getitemstring(row,'column_name')//将当前行操作符赋值给变量operator=dw_2.getitemstring(row,'operator')//将当前行查询内容赋值给变量content=dw_2.getitemstring(row,'content')//将当前行连接符赋值给变量(andor)join=dw_2.getitemstring(row,'join')//将查询条件窗口的空行删掉ifrow<>1thenif(isnull(column_name)or&
isnull(operator)or&isnull(content))thendw_2.deleterow(row)endifendif////将查询条件窗口的总行数赋值给变量row_count=dw_2.rowcount()//where后的表达式fori=1torow_countitem=dw_2.getitemstring(i,'column_name')operator1=dw_2.getitemstring(i,'operator')choosecaseitem//查询项为字符型case'name','author','publishing_house','sort','isbn','keeper','memo'ifi<>row_countthen//查询条件有多行时choosecaseoperator1case'not'//操作符为不包含
condition[i]=dw_2.getitemstring(i,'column_name')+""+&
dw_2.getitemstring(i,'operator')+""+"like"+&"'"+'%'+dw_2.getitemstring(i,'content')+'%'+"'"+dw_2.getitemstring(i,'join')+""case'like'//操作符为包含condition[i]=dw_2.getitemstring(i,'column_name')+""+&
dw_2.getitemstring(i,'operator')+""+&
"'"+'%'+dw_2.getitemstring(i,'content')+'%'+"'"+dw_2.getitemstring(i,'join')+""
case'=','<>'//操作符为等于或不等于
condition[i]=dw_2.getitemstring(i,'column_name')+""+&dw_2.getitemstring(i,'operator')+""+&
"'"+dw_2.getitemstring(i,'content')+"'"+dw_2.getitemstring(i,'join')+""endchooseelse//查询条件只有一行choosecaseoperator1case'not'//操作符为不包含
condition[i]=dw_2.getitemstring(i,'column_name')+""+&
dw_2.getitemstring(i,'operator')+""+"like"+&
"'"+'%'+dw_2.getitemstring(i,'content')+'%'+"'"case'like'//操作符为包含
condition[i]=dw_2.getitemstring(i,'column_name')+""+&dw_2.getitemstring(i,'operator')+""+&
"'"+'%'+dw_2.getitemstring(i,'content')+'%'+"'"case'=','<>'//操作符为等于或不等于condition[i]=dw_2.getitemstring(i,'column_name')+""+&
dw_2.getitemstring(i,'operator')+""+&
"'"+dw_2.getitemstring(i,'content')+"'"endchooseendif//查询项为日期类型case'publishing_date','buy_date'ifi<>row_countthen//查询条件有多行时condition[i]=item+""+dw_2.getitemstring(i,'operator')+""+&"date('"+dw_2.getitemstring(i,'content')+"')"+dw_2.getitemstring(i,'join')+""else//查询条件只有一行condition[i]=item+""+dw_2.getitemstring(i,'operator')+""+&
"date('"+dw_2.getitemstring(i,'content')+"')"endifendchoosenext//最终的where后的表达式new_condition=''fori=1torow_countnew_condition=new_condition+condition[i]nextold_sql1=dw_1.getsqlselect()new_sql1=old_sql1+"where"+new_condition//对原有数据窗口进行新的查询dw_1.reset()ifdw_1.setsqlselect(new_sql1)=-1thenbeep(3)
messagebox("警告","检索失败",stopsign!)elsedw_1.settransobject(sqlca)
dw_1.retrieve()
dw_1.setsqlselect(old_sql1)endif5.3.3更新打印模块实现图5-6更新打印窗口控件:pb_7“修改”事件(event):Clicked
ScriptofClickedfile://取消亮条显示一行,便于进行编辑dw_1.selectrow(dw_1.getrow(),false)//将数据窗口属性设为可以修改dw_1.Object.DataWindow.ReadOnly="no"dw_1.settransobject(sqlca)//将焦点设置在数据窗口控件上dw_1.setfocus()//触发dw_1的Getfocus事件dw_1.TriggerEvent(Getfocus!)//将
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论