数据建模
数据库设计——项目管理
1.逻辑数据库设计
1.1 项目管理
1.1.1数据需求
1.顾问公司
一个顾问公司有很多需要管理的项目。
2.项目
每个项目的详细信息包括项目编号、项目名称、计划开始日期、计划截止日期、实际开始日期、实际截止日期、工程计划费用、工程实际费用、客户编号、经理员工号。每个项目有一个用户和一个经理。在整个项目中,项目编号是唯一的。
3.客户
客户信息包括客户编号、客户姓名、客户地址(由城市、街道、州和邮政编码组成)、客户电话号、客户传真号、客户网址、联系人姓名、联系人电话、联系人传真号。其中客户编号唯一。
4.工作包
工作包信息包括工作包编号、计划开始日期、计划截止日期、实际开始日期、实际截止日期、工程计划费用、项目实际费用、项目号。其中,工作包编号是唯一的。
5.员工
员工中每个成员的详细信息包括员工号、角色开始日期、姓名、地址(街区、城市、州、邮编)、工作电话号码、家庭电话号码、传真号、职位、性别、薪水、入职日期、角色号。在整个项目中,员工号是唯一的。员工包括经理、普通员工。
6.角色
角色由角色编号、角色描述、单价。其中,角色编号唯一。
7.文档
文档编号、文档题目、文档日期、版本号、工作包号、撰写员工号。其中文档编号唯一。
8.文档作者
撰写文档的员工包括文档号和员工号。其中文档号和员工号唯一。
9.费用
费用包含信息为费用编号、支出日期、费用描述、花费金额、工作包号、员工号、费用类型号。其中费用编号为主键。
10. 费用类型
费用类型包含信息为费用类型号、费用类型描述。其中,费用类型号是唯一的。
11. 时间
时间信息包含信息为工作包号、员工号、开始工作时间、结束工作时间、工作时间。其中工作包号和员工号唯一。
12. 经理
是员工种类的一种,管理项目,下属很多员工。包含信息为员工号、姓名、地址(街区、城市、州、邮编)、工作电话号码、家庭电话号码、传真号、职位、性别、薪水、入职日期。在整个业务中,员工号是唯一的。
1.1.2事务需求
1.数据库应该支持下述事务
(a) 创建和维护记录各项目的详细信息和每个员工的记录。
(b) 创建和维护记录客户的详细信息和记录。
(c) 创建和维护员工的详细信息。
(d) 创建和维护记录文档的详细信息和详细记录。
(e) 创建和维护记录角色的信息。
(f) 创建和维护记录工作包的详细信息。
(g) 创建和维护记录费用类型的信息。
(h) 创建和维护记录文档作者的详细信息和详细记录。
2.数据应该能够支持下述查询事务
(a) 以表单形式列出项目名字、经理名字、客户号、客户电话,按项目编码排序。
(b) 以表单形式列出员工的姓名、号码、角色、工作时间,以及他们的项目的详细信息。
(c) 以报表形式列出项目的费用以及费用类型。
(d) 以报表形式列出项目的文档以及文档作者。
1.2使用逻辑数据库设计方法
1.2.1步骤1.1: 标识实体
逻辑数据库设计的第一个步骤是标识在数据库中必须表述的主实体。有上面的描述,可以标识如下实体:
Project(项目) Document(文档)
Client(客户) DocumentAuther(文档作者)
WorkPackage(工作包) Expense(费用)
Employee(员工)
1.2.2步骤1.2:标识关系
标识完实体后,下一步就是标识存在于这些实体间的所有关系。对于房屋租赁公司的实体关系,如图所示。
图1
1. 确定关系的多样性约束
标识完要创建的关系后,现在应该确定每个关系的多样性约束。
图2
2. 使用实体-关系(ER)建模
在数据库设计阶段,将创建几个ER模型。其中员工有自身的一对多的关系,员工和项目是多对多的管理关系,客户和项目是一对多的任命关系,员工和文档通过工作包具有多对多的关系其中工作包产生文档,工作包和费用是一对一的产生关系,文档作者和文档是一对多的编写的关系。故有如下ER图。
图3
1.2.3步骤1.3:标识实体或关系的有关属性
下一个步骤是标识与已经标识的实体或关系有关的属性。对于项目管理而言,应该标识如图所示的与实体有关的属性。
图4
1.2.4步骤1.4:确定属性域
现在要为上一步在数据字典中所标识的属性添加必要的属性域。
1. 合法的电话号码的属性域是一个10位的数字串。
1.2.5步骤1.5:确定候选键、主键和备用键属性
这个步骤主要是为实体标识候选键,然后选择其中之一作为主键。在标识主键的过程中,要特别注意实体是强实体还是弱实体。其中的分公司client离开了project将不存在,故client依赖于project为弱实体;Employee离开了project还是存在的实体,故Employee不依赖于project为强实体;DocumentAuther为强实体。但是Expense、Document都是依赖于Project而存在的,故二者均为弱实体。
在标识候选键时,应该注意到各个实体的主键及环境的考虑。如图所示。
1.2.6步骤1.6:特化和泛化实体
在Employee中包含Manager,故可泛化出1个实体。
1.2.7步骤1.7:检查模型的数据冗余
现在得到了一个项目管理的逻辑数据模型。但是这个数据模型包含一些应该被删除的冗余。特别需要注意的是:
1. 重新检查一对一关系。
2. 删除冗余关系。
1.2.8步骤1.8:检查模型是否支持用户事务
在这个步骤中,检查已经创建的局部逻辑数据模型是否支持用户所需的事务。检查包括:
1.数据模型中是否存在必要的属性。
2.如果属性要从多个实体中得到,则两个实体间是否有通路;换而言之,在两个实体间要有已经标识了的关系。
1.2.9步骤2.1:创建表
在这个步骤中,从逻辑数据模型创建表达用户视图中所描述的实体和关系的表,这时,要为关系数据库使用数据库设计语言(DDL)。将从逻辑数据模型创建表的全部结构都存档。
create table Project
(
projectNo char(10) primary key,
projectName char(15) not NULL,
plannedStartDate datetime not null,
plannedEndDate datetime not null,
actualStartDate datetime not null,
actualEndDate datetime not null,
projectedCost char(10) not NULL;
actualCost char(10) not NULL;
clientNo char(10) not NULL;
managerEmployeeNo char(10) not NULL;
)
create table Employee
(
emNo char(10) not NULL primary key,
emName char(10) not NULL,
emStreet char(10) not NULL,
emCity char(10) not NULL,
emState char(10) not NULL,
emZipCode char(10) not NULL,
emTel char(10) not NULL,
emPosition char(10) not NULL,
emsex char(10) not NULL,
emSalary char(10) not NULL,
RoleNo char(10)not NULL,
foreign key RoleNo references Role (RoleNo)
);
create table Client
(
clientNo char(10) not NULL primary key,
clientName char(10) not NULL,
clientStreet char(10) not NULL,
clientCity char(10) not NULL,
clientState char(10) not NULL,
clientZipCode char(10) not NULL,
clientTel char(10) not NULL,
clientFaxNo char(10) not NULL;
clientWebAdd char(10) not NULL,
contractName char(10) not NULL,
contractTel char(10) not NULL,
contractFaxNo char(10) not NULL;
contractEmailAdd char(10) not NULL,
);
create table Role
(
RoleNo char(10) not NULL primary key,
RoleDescription char(50) not NULL;
billingRate char(10) not NULL;
);
create table WorkPackage
(
wNo char(10) not NULL,
plannedStartDate datetime not null,
plannedEndDate datetime not null,
actualStartDate datetime not null,
actualEndDate datetime not null,
projectedCost char(10) not NULL;
actualCost char(10) not NULL;
ProjectNo char(10) not NULL;
);
create table Document
(
documentNo char(10) primary key,
documentTitle char(15) not NULL,
documentDate datetime not null,
versionNo char(15) not null,
workPackageNo char(15) not null,
appByEmNo char(15) not null ,
foreign key workPackageNo references workPackage (workPackageNo),
foreign key appByEmNo references Employee (employeeNo),
);
create table DocumentAuther
(
documentNo char(10),
emNo char(10) not NULL,
foreign key documentNo references document (documentNo),
foreign key emNo references Employee(emNo)
);
create table Expense
(
expenseNo char(10) primary key,
expenseDate datetime not null,
expenseDescription char(50) not NULL
expenseAmount char(10) not null,
workPackageNo char(10) not null,
emNo char(10) not null,
expenseTypeNo char(10) not null,
foreign key workPackageNo references workPackage (workPackageNo),
foreign key emNo references Employee(emNo)
foreign key expenseTypeNo references expenseType (expenseTypeNo)
);
create table expenseType
(
expenseType No char(10) not NULL primary key,
expenseType Description char(50) not NULL;
);
create table TimeBooked
(
wNo char(10) not NULL,
emNo char(10) not NULL,
dateStartWork datetime not null,
dateEndWork datetime not null,
timeWorked datetime not null,
foreign key workPackageNo references workPackage (workPackageNo),
foreign key emNo references Employee(emNo)
);
1.3.0步骤2.2:用规范化方法检查表结构
在这个步骤中,要确保上一步所建的表至少要满足第三范式(3NF)。如果满足不了第三范式,则可能是逻辑数据模型中的某些部分是错误的,或者是从模型产生表的时候产生了错误。
1.3.1步骤2.3:检查模型是否支持用户事务
这个步骤与步骤1.8类似,在这个步骤中,除了要检查从实体到表的映射关系并且要确定外键之外,在这个情景下,还可以再次检查从实体到表的映射是否正确地完成,以及所创建的表是否支持标识的用户事务。
1.3.2步骤2.4:检查业务规则
业务规则是为了防止数据库不一致而强加的约束。六种完整性约束中,有四种在上一步已经标识了,并且存档在数据字典中。这四种是:需要的数据、属性域的约束、实体完整性和多样性。剩下两种为:参照完整性和其他业务规则。
1.参照完整性
考虑两点:
(1)标识外键是否可以为空(NULL)。通常,如果关系中子表部分是强制的,那么就不允许为空。如果子表部分是可选的,那么就允许为空。
(2)标识现有约束条件,表明外键的插入、更新或者产出情况。通常,要为每个外键明确说明两个动作:一个是ON UPDATE动作,另一个是ON DELETE动作,用于表明当在父表中更新或删除一条记录时,如何保证参照完整性。
2.物理数据库设计
2.1步骤3.1:设计基本表
在逻辑数据库设计阶段,创建了一些描述逻辑数据模型中的实体关系和关系的基本表的设计包括:
·对每个表,包括它的属性、主键、备用键、外键和完整性约束。
·对每个属性,包括它的域、可选的默认值、是否可以为空和是否是派生的。
基本表的设计还包括,使用这些信息去定义域、默认值和空指示符。
2.1.1创建基本表
下面利用Orcale为例建表,因此可以这样定义:
·主键,使用PRIMARY KEY子句。
·备用键,使用UNIQUE子句。
·非空列,使用 NOT NULL子句。
·外键,使用FOREIGN KEY子句。
·其他列或表约束,使用CHECK和CONSTRAINT子句。
2.2.2 建立空表
create table Project
(
project No char(10) primary key,
projectName char(15) not NULL,
plannedStartDate datetime not null,
plannedEndDate datetime not null,
actualStartDate datetime not null,
actualEndDate datetime not null,
projectedCost char(10) not NULL;
actualCost char(10) not NULL;
clientNo char(10) not NULL;
managerEmployeeNo char(10) not NULL;
)
create table Employee
(
emNo char(10) not NULL primary key,
emName char(10) not NULL,
emStreet char(10) not NULL,
emCity char(10) not NULL,
emState char(10) not NULL,
emZipCode char(10) not NULL,
emTel char(10) not NULL,
emPosition char(10) not NULL,
emsex char(10) not NULL,
emSalary char(10) not NULL,
RoleNo char(10)not NULL,
foreign key RoleNo references Role (RoleNo)
);
create table Client
(
clientNo char(10) not NULL primary key,
clientName char(10) not NULL,
clientStreet char(10) not NULL,
clientCity char(10) not NULL,
clientState char(10) not NULL,
clientZipCode char(10) not NULL,
clientTel char(10) not NULL,
clientFaxNo char(10) not NULL;
clientWebAdd char(10) not NULL,
contractName char(10) not NULL,
contractTel char(10) not NULL,
contractFaxNo char(10) not NULL;
contractEmailAdd char(10) not NULL,
);
create table Role
(
RoleNo char(10) not NULL primary key,
RoleDescription char(50) not NULL;
billingRate char(10) not NULL;
);
create table WorkPackage
(
wNo char(10) not NULL,
plannedStartDate datetime not null,
plannedEndDate datetime not null,
actualStartDate datetime not null,
actualEndDate datetime not null,
projectedCost char(10) not NULL;
actualCost char(10) not NULL;
ProjectNo char(10) not NULL;
);
create table Document
(
documentNo char(10) primary key,
documentTitle char(15) not NULL,
documentDate datetime not null,
versionNo char(15) not null,
workPackageNo char(15) not null,
appByEmNo char(15) not null ,
foreign key workPackageNo references workPackage (workPackageNo),
foreign key appByEmNo references Employee (employeeNo),
);
create table DocumentAuther
(
documentNo char(10),
emNo char(10) not NULL,
foreign key documentNo references document (documentNo),
foreign key emNo references Employee(emNo)
);
create table Expense
(
expenseNo char(10) primary key,
expenseDate datetime not null,
expenseDescription char(50) not NULL
expenseAmount char(10) not null,
workPackageNo char(10) not null,
emNo char(10) not null,
expenseTypeNo char(10) not null,
foreign key workPackageNo references workPackage (workPackageNo),
foreign key emNo references Employee(emNo)
foreign key expenseTypeNo references expenseType (expenseTypeNo)
);
create table expenseType
(
expenseType No char(10) not NULL primary key,
expenseType Description char(50) not NULL;
);
create table TimeBooked
(
wNo char(10) not NULL,
emNo char(10) not NULL,
dateStartWork datetime not null,
dateEndWork datetime not null,
timeWorked datetime not null,
foreign key workPackageNo references workPackage (workPackageNo),
foreign key emNo references Employee(emNo)
);
2.2 步骤2.2:设计派生数据的表示
在1.1.1中给定需求表明的派生项中,其中一个为计算租借金额总费用。获得该信息的SQL语句为:
Select *
From Lease
Where
2.3 步骤2.3:设计其他业务规则
有时,更改表可能会受到业务规则的限制。这些规则的设计也依赖于目标DBMS。有些系统在定义规则方面比另一些系统提供了更多的功能。这些即是CHECK和CONSTRAINT子句、before triggers(前触发器)、after triggers(后触发器)定义其他约束。
2.4 步骤4.1:分析事物
创建了基本表,完整性约束和业务规则后,下一步就是分析事物为每个基本表确定适合的文件组织方式和索引。在房地产租赁系统中,最重要的的事务是房地产租赁PropertyForRent表。为了集中在可能出现问题的区域,我们采用的方法是:
1. 将所有的事物路径映射到表。
2. 确定最长被实务访问的表。
3. 分析涉及到这些表的事务。