在做机房收费系统个人版的时候又一次的遇到了数据库设计方面的内容,还记得第一次机房收费系统的时候,数据库的设计基本上是边敲边设计的,搞得特别的乱,也不符合编程的规范。既然我们现在已经是专业人士了,那么就应该采取一些专业的手段来设计,并且一个数据库设计的好坏直接影响到后台数据,对软件的运行效率也是密切联系的。下面就分享下这次做数据库的心得。
ER模型
在自学考试中,学习过有关ER模型方面的知识,这是被广泛被采用的概念模型设计方法,就是所谓的图形的方式来展示用户需求中各方面的联系,这与Use Case是不一样,用例图只是单一的展示了用户的需求,没有加入任何的关系操作,而ER模型在此基础上引入了联系的基本元素。
基本元素
实体:一个数据对象,指应用中可以区别的客观存在的事物
联系:表示多个实体间的关系
属性:实体的某一特性
操作方法
1.分析需求
下面机房收费系统中用户的描述
学生:可以上机,查看自己的余额,查看自己的上机记录,还有自己的充值记录,并且可以自己修改自己的密码。
值班教师:我是机房的值班老师,由我来管理学生的上机情况,我的职责是负责同学上机,并且可以帮助
同学注册,充值和退卡,也可以管理学生的上机情况。当然了也可以查看今天收取金额的情况。
管理员:我可以管理值班教师,比如添加和删除值班教师,查看他们的工作记录,并且我也可以
把近段时间来的金额进行汇总结账,只能由我来设置学生上机消费的金额信息信息
2.设计局部ER模型
2.1 确定局部结构的范围
我们从用户的需求中,然后根据用户的不同职责来划分出范围(学生、值班教师、管理员)
2.2 定义实体
这就需要从每一个局部的结构中概括出一些实体类型
比如学生这个职责范围内的实体(学生、上机情况、余额情况、密码等)
2.3 定义联系
为实体与实体之间根据需求分析的结果,考察是否存在联系
2.4 分配属性
最后根据需求分析的结果,为每一个实体定义自己的特性,例如学生的属性有——姓名、卡号、性别等
下面是学生ER图的连接http://my.csdn.net/my/album/detail/1764165
3.设计全局ER模型
3.1 确定公共实体
当分别设计完局部的ER图后,就可以把局部合并成为全局,在合并的过程中也要合并实体,因为不同
的类别范围内查找的实体可能会重复。
3.2 合并局部ER模型
在确定完公共实体后,就可以根据公共的实体来合并局部的ER图
下面是合并完后全局ER图的连接http://my.csdn.net/my/album/show/274159
通过ER模型我们就能够很清楚的了解到软件项目中包括的实体,以及实体与实体之间的联系,就能够从宏观上
把握软件的架构。
关系模型
所谓的关系模型简单的说就是我们数据库中一张一张的表,当然了数据库中的数据也有自己的设置规则
1.1 实体参照性规范
主键值不能为空,否则主键就起不到惟一标识的作用
1.2参照完整性原则
在数据表中的外键值不是空值就是定于其他表的主键值
1.3 用户定义完整性规则
为了方便用户的管理,用户还可以自己制定相应的数据约束
ER模型到关系模型的转变
在ER模型中有:实体、联系和属性,我们知道在数据库中有记录、字段和表名
这些都是相互对应的,下面就说一下如何来从ER模型来转变为关系模型
转变
1.1 实体转换为模型
1.2 若实体间联系是1:1,则可以在两个实体间加入任何一个实体的主键值
1.3 若实体间联系是M:N,则可以把两个实体的主键提取出来重新组合成新的关系
最后机房收费系统后的关系模型如下:
教师(教工号、水平、年龄、性别、姓名、状态) |
学生(卡号、学号、班级、年级、性别、姓名、系、密码、状态) |
退款记录(学生卡号、教工号、值班教师、退款日期,退款金额,退款人员、退款时间) |
收取金额(学生卡号、教工号、值班教师,收取日期、收取金额、收款人) |
基本数据(教职工号、临时用户费用、递增时间、至少上机时间、准备时间、最少金额) |
值班记录(教工号、值班教师、值班日期、值班时间、下机日期) |
充值记录(学生卡号、充值教师、充值金额、充值日期、充值时间) |
上机记录(学生卡号、上机日期、上机时间、下机日期、下机时间) |
日结账单(教工号、上次余额、本日消费金额、本日充值金额、本日退款金额、日期) |
周结账单(教工号、上周余额、本期消费金额、本期充值金额、本期退款金额、日期) |
优化
1 消除重复
我们看到教师查看收取金额记录和学生的充值记录是重复的,所以需要去除重复来消除冗余。
2.三范式
1NF:表中的列是不可以在分的(原子性)
例如一张员工信息的表(姓名、住址、电话号码),但是员工的电话号码又分为住址号码和手机号码,所以就违反了1NF
要修改的话,要不就把电话号码的属性拆分为住址号码和手机号码,要不就强制员工直流一个号码
2NF:表中不存在重复的记录(即表中的行是不可以重复的)
我们就拿上面机房收费系统设计出来的表为例,学生信息表(学号、姓名、班级、系别)。如果这样设计的话,我们可以知道一个系里面大概有1000多名学生,那么这个字段就会在这站张表中重复1000多次,而且还有班级这个字段也是同样的道理
这样做的话就会造成
数据冗余:一站表中多次出现了重复的记录
更新异常:若要调整表中系别的字段的话,所有的系别都需要更新,有可能出现同一个学生出现在不同的系里面
插入异常:如果学校新开一个系别,如果没有学生的话,那么这个系别无法保存进去
要改的话把系别和学生信息区别开来(系别号、系别)和(学号、系别号、姓名、性别),然后这两张表通过系别号来进行连接
3NF:一个表中的列不依赖与另一个表中的非主键的列
其实数据库的要求就是要遵从概念单一化"一事一地"原则,即一个关系模式描述一个实体或者实体间的一种联系。通过三范式的约束后,我们来看一下最后的数据库
教师(教工号、系别号、年龄、性别、姓名、状态) |
系(系别号、系) |
学生(卡号、学号、班级、年级、性别、姓名、系、密码、状态) |
退款记录(学生卡号、教工号、值班教师、退款日期,退款金额,退款人员、退款时间) |
基本数据(教职工号、临时用户费用、递增时间、至少上机时间、准备时间、最少金额) |
值班记录(教工号、值班教师、值班日期、值班时间、下机日期) |
充值记录(学生卡号、充值教师、充值金额、充值日期、充值时间) |
上机记录(学生卡号、上机日期、上机时间、下机日期、下机时间) |
日结账单(教工号、上次余额、本日消费金额、本日充值金额、本日退款金额、日期) |
周结账单(教工号、上周余额、本期消费金额、本期充值金额、本期退款金额、日期) |