数据库的三大范式和五个要求

以下内容整理来至网络

三大范式的规范

例:

create table sample(
prjnum integer not null,
prjname varchar(200),
emynum interger not null,
emyname varchar(200),
salcategory char(1),
salpackage  integer
);
alter table senssic add primary key (prjnum,enynum);
数据:

prjnum      prjname      emynum      emyname      salcategory     salpackage
1001         tpms            2001             senssic            A                        2000
1001         tpms            2002             qiyu                   B                        3000
1001         tpms            2003             sen                   C                        4000
1002         tct                 2001              yu                      A                        2000
1002         tct                 2004              ssic                  B                        3000

0.函数依赖:

        某个属性集决定另一个属性集时,称另一属性集依赖于该属性集,x→y,则x决定y或y依赖x

        非平凡函数依赖:(学号,课程号)->成绩 x->y但y不为x的子集即x->y为非平凡函数依赖
        平凡函数依赖: (学号,课程号)->学号   (学号,课程号)->课程号 x->y但y为x的子集即x->y为平凡函数依赖

        部分函数依赖:(学号,姓名)→ 性别,学号 → 性别,所以(学号,姓名)→ 性别 是部分函数依赖

        完全函数依赖:(学号,课程号)→ 成绩,学号 !→ 成绩,课程号 !→ 成绩,所以(学号,课程号)→ 成绩 是完全函数依赖

       传递函数依赖:学号 → 系名,系名 → 系主任,并且 系名 !→ 学号,所以 学号 → 系主任 为传递函数依赖

1.1NF(第一范式)

    定义  若关系模式R的每一个分量是不可再分的数据项,则关系模式R属于第一范式(1NF)。

参照范式的定义,考察上表,我们发现,这张表已经满足了第一范式的要求。

1、因为这张表中字段都是单一属性的,不可再分;

2、而且每一行的记录都是没有重复的;

3、存在主属性,而且所有的属性都是依赖于主属性;

4、所有的主属性都已经定义

事实上在当前所有的关系数据库管理系统(DBMS)中,都已经在建表的时候强制满足第一范式。属性对<Project Number, Employee Number>是主键,

其他所有的属性都依赖于该主键。

 2.2NF(第二范式)

    定义  若关系模式R1NF,且每一个非主属性完全依赖于码,则关系模式R2NF。

               即当1NF消除了非主属性对码的部分函数依赖,则成为 2NF。

由表可以看出非主属性<Project Name>部分依赖于主键中的<Project Number>; 非主属性<Employee Name>,<Salary Category>和<Salary package>都部分依赖于主键中的<Employee Number>;

存在着以下潜在问题:

1. 数据冗余:每一个字段都有值重复;

2. 更新异常:比如<Project Name>字段的值,比如对值"tmps"了修改,那么就要一次更新该字段的多个值;

3. 插入异常:如果新建了一个Project,名字为TPT, 但是还没有Employee加入,那么<Employee Number>将会空缺,而该字段是主键的一部分,因此将无法插入记录;

 4.删除异常:如果一个员工 2003,sen  离职了,要将该员工的记录从表中删除,而此时相关的Salary信息 C 也将丢失, 因为再没有别的行纪录下

 Salary C的信息。

因此,我们需要将存在部分依赖关系的主属性和非主属性从满足第一范式的表中分离出来,形成一张新的表,而新表和旧表之间是一对多的关系。

所以将上表拆分以下三张表:

create table project(
  prjnum   integer not null,
  prjname varchar(200)
)
alter table project add primary key(prjnum);
create table employee(
  emynum integer not null,
  emyname varchar(200),
  salcategory  char(1),
  salpackage integer
)
alter table employee add primary key(emynum); 

create table prj_emy(
    prjnum integer not null,
    emynum  integer   not null 
)
alter table prj_emy add primary key(prjnum,emynum);

3.3NF(第三范式)

        定义  若关系模式R(U,F)中不存在这样的码X,属性组Y及非主属性Z(ZY)使得XY,(YX)YZ成立,则关系模式R3NF。

               即当2NF消除了非主属性对码的传递函数依赖,则成为3NF。

前面生成的三张表,我们发现,employee表存在传递依赖关系,即:关键字段< Employee Number > --> 非关键字段< Salary Category > -->非关键字段< Salary Package >。而这是不满足三范式的规则的,存在以下的不足:

1、 数据冗余:<Salary Category>和<Salary Package>的值有重复;

2、 更新异常:有重复的冗余信息,修改时需要同时修改多条记录,否则会出现数据不一致的情况;

3、 删除异常:同样的,如果员工 2003 sen离开了公司,会直接导致 Salary C 的信息的丢失。

所以可将此表拆分为

create table emp_sal(
  emynum integer not null,
  emyname varchar(200),
  salcategory  char(1)
)
alter table emp_sal add primary key(emynum);
create table ca_pa(
  salcategory char(1),
  salpackage integer
)

4.三大范式的本质

 三大范式本质:

第一范式:字段唯一,凡是关系型数据库都满足,所以一般不用管

第二范式:满足第一范式,每个键都唯一,即每行数据都唯一,没有重复的行数据,一般使用主键或复合主键

第三范式:满足第二范式,且每两个设计实体之前都无相同(相同功能作用)的字段,如果只使用一张表,字段冗余(重复)很大,所以要两张以上表以关系形式维护(一对多或多对一,一对一意义不大因为完全可以设计成一张表),第三范式目的就是消除冗余,如果需要其字段使用外键(外键一般都需要建立索引)来参照(参照主键或   (候选键:唯一索引))来关联
   有时候为了满足应用性能,二范式也是值得选择的
 

5.主键候选键超键外键的区别

超键(super key):在关系中能唯一标识元组的属性集称为关系模式的超键
候选键(candidate key):不含有多余属性的超键称为候选键 
主键(primary key):用户选作元组标识的一个候选键程序主键 比如一个小范围的所有人,没有重名的
外键:在关系模式R中,如果某属性集是其他模式的主键或 候选键(索引唯一) ,那么该属性集对模式R来说就是外键
考虑以下属性 身份证 姓名 性别 年龄 身份证唯一,所以是一个超键 
姓名唯一,所以是一个超键 
(姓名,性别)唯一,所以是一个超键 
(姓名,性别,年龄)唯一,所以是一个超键 
--这里可以看出, 超键的组合是唯一的,但可能不是最小唯一的 
身份证唯一,而且没有多余属性,所以是一个候选键 
姓名唯一,而且没有多余属性,所以是一个候选键 
--这里可以看出, 候选键是没有多余属性的超键(即一个)
考虑输入查询方便性,可以选择 身份证 为主键 也可以 考虑习惯 选择 姓名 为主键 
-- 主键是选中的一个候选键(即一个,如果多个主键叫做复合主键)

数据库设计规范化的五个要求

      要求一:表中应该避免可为空的列。 

  虽然表中允许空列,但是空字段是一种比较特殊的数据类型。数据库在处理的时候,需要进行特殊的处理。如此的话,就会增加数据库处理记录的复杂性。当表中有比较多的空字段时,在同等条件下,数据库处理的性能会降低许多。通过设置默认值的形式,来避免空字段的产生。身份证号码字段往往不能及时提供。身份证号码字段可以允许为空,以满足这些特殊情况的需要。但是,在数据库设计的时候,则可以做一些处理。如当用户没有输入内容的时候,则把这个字段的默认值设置为0或者为N/A。以避免空字段的产生。 
  二是若一张表中,允许为空的列比较多,接近表全部列数的三分之一。而且,这些列在大部分情况下,都是可有可无的。若数据库管理员遇到这种情况,建议另外建立一张副表,以保存这些列。然后通过关键字把主表跟这张副表关联起来。将数据存储在两个独立的表中使得主表的设计更为简单,同时也能够满足存储空值信息的需要。 

  要求二:表不应该有重复的值或者列。 

  如现在有一个进销存管理系统,这个系统中有一张产品基本信息表中。这个产品开发有时候可以是一个人完成,而有时候又需要多个人合作才能够完成。所以,在产品基本信息表产品开发者这个字段中,有时候可能需要填入多个开发者的名字。 
  如进销存管理中,还需要对客户的联系人进行管理。有时候,企业可能只知道客户一个采购员的姓名。但是在必要的情况下,企业需要对客户的采购代表、仓库人员、财务人员共同进行管理。因为在订单上,可能需要填入采购代表的名字;可是在出货单上,则需要填入仓库管理人员的名字等等。 
  为了解决这个问题,有多种实现方式。但是,若设计不合理的话在,则会导致重复的值或者列。如我们也可以这么设计,把客户信息、联系人都放入同一张表中。为了解决多个联系人的问题,可以设置第一联系人、第一联系人电话、第二联系人、第二联系人电话等等。若还有第三联系人、第四联系人等等,则往往还需要加入更多的字段。 
  可是这么设计的话,会产生一系列的问题。如客户的采购员流动性比较大,在一年内换了六个采购员。此时,在系统中该如何管理呢?难道就建立六个联系人字段?这不但会导致空字段的增加,还需要频繁的更改数据库表结构。明显,这么做是不合理的。也有人说,可以直接修改采购员的名字呀。可是这么处理的话,会把原先采购订单上采购员的名字也改变了。因为采购单上客户采购员信息在数据库中存储的不是采购员的名字,而只是采购员对应的一个编号。在编号不改而名字改变了的情况下,采购订单上显示的就是更改后的名字。这不利于时候的追踪。 
  所以,在数据库设计的时候要尽量避免这种重复的值或者列的产生。建议,若数据库管理员遇到这种情况,可以改变一下策略。如把客户联系人另外设置一张表。然后通过客户ID把供应商信息表跟客户联系人信息表连接起来。也就是说,尽量将重复的值放置到一张独立的表中进行管理。然后通过视图或者其他手段把这些独立的表联系起来。 

   要求三:表中记录应该有一个唯一的标识符。

  在数据库表设计的时候,数据库管理员应该养成一个好习惯,用一个ID号来唯一的标识行记录,而不要通过名字、编号等字段来对纪录进行区分。每个表都应该有一个ID列,任何两个记录都不可以共享同一个ID值。另外,这个ID值最好有数据库来进行自动管理,而不要把这个任务给前台应用程序。否则的话,很容易产生ID值不统一的情况。 
  另外,在数据库设计的时候,最好还能够加入行号。如在销售订单管理中,ID号是用户不能够维护的。但是,行号用户就可以维护。如在销售订单的行中,用户可以通过调整行号的大小来对订单行进行排序。通常情况下,ID列是以1为单位递进的。但是,行号就要以10为单位累进。如此,正常情况下,行号就以10、20、30依次扩展下去。若此时用户需要把行号为30的纪录调到第一行显示。此时,用户在不能够更改ID列的情况下,可以更改行号来实现。如可以把行号改为1,在排序时就可以按行号来进行排序。如此的话,原来行号为30的纪录现在行号变为了1,就可以在第一行中显示。这是在实际应用程序设计中对ID列的一个有效补充。这个内容在教科书上是没有的。需要在实际应用程序设计中,才会掌握到这个技巧。 

  要求四:数据库对象要有统一的前缀名。 

  一个比较复杂的应用系统,其对应的数据库表往往以千计。若让数据库管理员看到对象名就了解这个数据库对象所起的作用,恐怕会比较困难。而且在数据库对象引用的时候,数据库管理员也会为不能迅速找到所需要的数据库对象而头疼。 
  为此,建议,在开发数据库之前,最好能够花一定的时间,去制定一个数据库对象的前缀命名规范。如在数据库设计时,喜欢跟前台应用程序协商,确定合理的命名规范。最常用的是根据前台应用程序的模块来定义后台数据库对象前缀名。如跟物料管理模块相关的表可以用M为前缀;而以订单管理相关的,则可以利用C作为前缀。具体采用什么前缀可以以用户的爱好而定义。但是,需要注意的是,这个命名规范应该在数据库管理员与前台应用程序开发者之间达成共识,并且严格按照这个命名规范来定义对象名。 
  其次,表、视图、函数等最好也有统一的前缀。如视图可以用V为前缀,而函数则可以利用F为前缀。如此数据库管理员无论是在日常管理还是对象引用的时候,都能够在最短的时间内找到自己所需要的对象。 

  要求五:尽量只存储单一实体类型的数据。

  这里将的实体类型跟数据类型不是一回事,要注意区分。这里讲的实体类型是指所需要描述对象的本身。举一个例子,估计大家就可以明白其中的内容了。如现在有一个图书馆里系统,有图书基本信息、作者信息两个实体对象。若用户要把这两个实体对象信息放在同一张表中也是可以的。如可以把表设计成图书名字、图书作者等等。可是如此设计的话,会给后续的维护带来不少的麻烦。 
  如当后续有图书出版时,则需要为每次出版的图书增加作者信息,这无疑会增加额外的存储空间,也会增加记录的长度。而且若作者的情况有所改变,如住址改变了以后,则还需要去更改每本书的记录。同时,若这个作者的图书从数据库中全部删除之后,这个作者的信息也就荡然无存了。很明显,这不符合数据库设计规范化的需求。 
  遇到这种情况时,建议可以把上面这张表分解成三种独立的表,分别为图书基本信息表、作者基本信息表、图书与作者对应表等等。如此设计以后,以上遇到的所有问题就都引刃而解了。 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值