数据冗余:关系型数据库的数据冗余主要是指关系数据库中同一信息数据的重复存储
数据冗余分类:
1.表的重复
2.属性的重复:不同表的属性重复,常用来建立表之间的联系只需一个公共属性,是必须的;同一表内属性重复,非数据安全检查需要,应删除。
3.属性值的重复:无限类属性值的重复;无限类属性值得重复
4.元组的重复:
数据冗余导致的问题:空间浪费、增加异常、删除异常和修改异常
数据冗余解决方案:引入外键约束,通过引入新的表,同时使用外键约束保证取值的合理性,从而减少数据冗余
1.主键( primary key ):
用表中的一个字段作为主键,用于唯一的标识表中的一条记录
2.公共关键字:
两个表中相同的属性,称为两个表的公共关键字
3.外键:
公共关键字在一个表中是主键,在另一个表中被称为外键,外键表示两个表之间
的关系,外键表示该列的允许取的值必须在另一个表的主键中出现
4.主表和从表:
以该公共关键字作主键的表被称为主表,具有此外键的表被称为主表的从表。
5.外键的特点:
从表中的外键的值是对应主表中主键值的引用
从表中的外键数据类型必须和主表中的主键数据类型一致
主键可分为2大类:自然主键和代理主键。一般建议使用代理主键
将表中的所有列的组合当作主键--候选码
去除其中某些列查看是否还能唯一标识一行数据
最后找到的所有候选码的真子集就是主码
创建外键语法1:
create table tb_product(
id bigint primary key auto_increment comment '商品标号',
-- 引入额外的列用于表示商品所属于的类别
catalog_id bigint, -- 外键列,允许为null
-- 外键表示该列的允许取的值必须在tb_catalog的id列中出现
foreign key(catalog_id) references tb_catalog(id)
) comment '商品表';
创建外键语法2:
create table tb_product(
id bigint primary key auto_increment comment '商品标号',
catalog_id bigint -- 外键列,允许为null。是否允许为空取决于业务规则
)
-- alter table 从表名称 add [constraint fk_catalog外键约束名称] foreign key(从表中
的外键列名) references 主表名称(主表中的主键列名称)
alter table tb_product add constraint fk_catalog foreign key(catalog_id)
references tb_catalog(id);
删除外键约束语法:
-- alter table 从表名称 drop foreign key 外键约束名称;
alter table tb_product drop foreign key fk_catalog;
设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。
目前关系数据库有5+1级范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。
所有列不可分,字段满足原子性
定义学生,学生(编号、班级编号、姓名、亲属),这个亲属列是可分的,所以将亲属列划分到另外表中,从而使剩余的列满足NF1,最终结构选择为 学生(编号、班级编号、姓名)、学生亲属(姓名、关系、外码)
消除对主键的部分依赖
定义学生,学生(编号、班级编号、姓名、宿舍楼号),主键为复合主键(编号、班级编号),这里会发现一旦班级编号确定则所属的系别就确定,系别确定则宿舍楼号确定。宿舍楼号部分依赖主键,不是依赖整个主键。解决问题的方法为分表 学生(编号、班级编号、姓名) 学生住宿 (班级编号、宿舍楼号)
消除对主键的传递依赖
定义学生,学生(学号pk、系别、宿舍楼号),主键为学号,所以自然满足NF2,但是一旦系别确定则宿舍楼号确定,所以宿舍楼号依赖于系别,不是依赖于学号。这里就是传递依赖:宿舍楼号-->系别-->学号pk。解决问题的方法为分表
应用范式可以减少数据冗余,但是范式级别越高,则创建表的数量越多,查询效率则越低。所以在具体开发中经常采用降低范式要求,采用合理冗余数据的方式以提高查询效率
考虑查询效率,所以一般只达到NF3即可,甚至有时会了提高查询效率会有意降低范式要求【反范式】
实体:
现实世界中客观存在并可以被区别的事物。比如“一个学生”、“一本书”、“一门课”等等。值得强调的是这里所说的“事物”不仅仅是看得见摸得着的“东西”,它也可以是虚拟的,不如说“老师与学校的关系”。
属性:
教科书上解释为:“实体所具有的某一特性”,由此可见,属性一开始是个逻辑概念,比如说,“性别”是“人”的一个属性。在关系数据库中,属性又是个物理概念,属性可以看作是“表的一列”。
元组:
表中的一行就是一个元组。
分量:
元组的某个属性值。在一个关系数据库中,它是一个操作原子,即关系数据库在做任何操作的时候,属性是“不可分的”。否则就不是关系数据库了。
码:
表中可以唯一确定一个元组的某个属性(或者属性组),如果这样的码有不止一个,那么叫候选码,从候选码中挑一个出来做老大,它就叫主码。
全码:
如果一个码包含了所有的属性,这个码就是全码。
主属性:
一个属性只要在任何一个候选码中都出现过,这个属性就是主属性。
非主属性:
与上面相反,没有在任何候选码中出现过,这个属性就是非主属性。
外码:
一个属性(或属性组),它不是码,但是它别的表的码,它就是外码。
候选码:
若关系中的某一属性或属性组的值能唯一的标识一个元组,而其任何真子集都不能再标识,则称该属性组为(超级码)候选码。
一对一
一对一实现方式有2种:共享主键或者唯一外键。
一对多
实际上默认情况下fk外键参照主键pk则就是一对多关联,例如一个人有多辆车,一个车只能属于一个人
多对多
实际上在关系型数据库中是不能直接表达多对多关系,必须引入中间表。