数据库范式对 数据库建表 和 策划建表填表 都有很重要的指导意义。
一、第一范式
1、概念:
在关系模型中,对于添加的一个规范要求,所有的域都应该是原子性的,即数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项。
2、快速理解:
表中各列应该相互独立、不重复、不分前后顺序、不可分割(也要看定义,如“个人简介”可作为一列String没问题。但也可拆分为“教育背景”“工作经历”“项目经验”等)。
二、第二范式
1、概念:
在1NF的基础上,非主码属性必须完全依赖于候选码(在1NF基础上消除非主属性对主码的部分函数依赖)。
2、快速理解:
对于多主键的表,每个主键都必须充分利用,否则将造成冗余(仅讨论主键和非主键)。
即:对于函数 y = f(x1, x2),不可只用x1或x2的某一个就能得到y。
违反第二范式的是将数据放错了层级!(实际经验,大多时候可能是为了省一张表)。
例:有M个商店,每个商店上有N个商品,对于商店的配置有Shop表(主键为ShopID),对于商品有商品表(双主键,分别为ShopID、GoodsID)。此时,如果仅有一个对于商店的配置 “商店名”,本应该填在Shop表中,但因为非主属性只有一列,所以程序/策划可能不愿意单独建表,就将它填在商品表中(这里主要指策划配置的Excel)。
个人看法:应该按逻辑实体准确建表(完全由“实体”和“关系”决定,不要因为表的属性少就想省掉)!逻辑上清晰准确是最重要的。“多一张表会增加维护成本” 绝对是个假命题。实际上无论是开发还是维护都不怕 “复杂” 而怕 “混乱” 。然而,有时候适当妥协也可,因为建表填表不是一个人的事,沟通和说服成本可能会很高(费时、争吵)。
三、第三范式
1、概念:
在2NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖)。
2、快速理解:
一张表中,只允许存在非主键对主键的依赖关系 f(x),不允许非主键之间的依赖关系(仅讨论主键和非主键)。
违反第三范式的是其关联的实体的属性放到了自己身上。(实际经验,可能没有捋清实体关系,或为了省一张表)。
例:有M个英雄,每个英雄都有一个所属阵营。然后建表为Hero表,主键为HeroID,非主键有 “英雄名”、“阵营名”、“阵营图标”、“阵营介绍”。。。(其中,阵营相关的字段,不是由英雄直接决定的,而是 “传递地” 由英雄所属的阵营决定的)
个人看法:对于关系型数据表,一定要理清 “实体” 和 “关系”,对于违反第三范式的表,应该拆出新表、由外键关联。如本例中,建立阵营表(主键为CampID,非主键为“阵营名”、“阵营图标”、“阵营介绍”,然后在英雄表中填写所属阵营外键 CampID)。
-------------------------- NRatel割 --------------------------
备注:
码(键、属性):一条属性或属性组。
候选码(超级码、候选关键字、关键字):若关系中的某一属性或属性组的值能唯一的标识一个元组,而其任何、子集都不能再标识,则称该属性或属性组为候选码。(一张表中可能有多个或多组候选码)
主码(主关键字、主键):主码/主键(primary key)是被挑选出来,作为表的行的唯一标识的候选码。(一个表只有一个主键。主键可由一个字段或多个字段组成(单主键/多主键))
主属性: 在一个关系中,如果一个属性是构成某一个候选码的属性集中的一个属性,则称它为主属性。(候选码中的属性)
非主属性:不包含在任何一个候选码中的属性称为非主属性(非候选码中的属性)。