一、数据库三大范式
我们构造数据库的时候必须要遵守一定的原则,那这个规则就是范式关系型数据库,一共有六种范式,一般情况下只需要满足第三范式即可。
第一范式:原子性构造数据库必须遵循一定的规则,这种规则就是范式目前关系型数据库有6中范式,一般情况下,只满足第三范式即可第一范式是数据库的基本要求,不满足这一点就不是关系数据库
第二范式:唯一性数据表中的每条记录必须是唯一的,为了实现区分,通常要为表加上一个列来存储唯一标识,这个唯一属性被称作主键列
第三范式:关联性每列都与主键有直接关系,不存在传递依赖
1.1、第一范式:原子性
第一范式是数据库的最基本要求,不满足第一范式就不是关系型数据库了,第一范式要求的是数据的原子性。原子是不可再分的粒子,我们定义数据表的时候,某个字段中的数据也要满足原子性,不可再分。
比如说有这么一条记录,刘娜同学的这个班级信息,是保存在班级这个字段里边的。那他的这个内容是高三年级一班这个数据就不符合原子性,因为数据还能继续拆分成年级和班级两个字段,这么拆分之后,我们检索数据的条件就更加灵活了,比如说我想查找高三年级的所有同学,那就可以根据年级这个字段很轻松的查找到他们。但是现在把年级和班级写在一起,我就不能根据年级去查找数据了。总结来说,数据表的每一列都是不可再分割的基本数据,同一列中不能有多个值,也只也不能存在着重复的属性
1.2、第二范式:唯一性
第二范式要求的是数据的唯一性,也就是说数据表中必须有一个字段,每条记录这个字段的值是不能重复的。
比如说有一个学号是230的同学参加计算机上的模拟考试,比如说2018年7月15号这一天他第一次模拟考试考了58分,于是这个同学觉得不理想,又考了一次果当结果当天的第二次考试成绩还是58分,那么问题就来了,在数据库里边是无法区分这两条记录是重复的还是不重复的?因为两条记录的内容是完全都一样的。为了能区分重复的数据,我们可以给数据表加上一个流水号儿的字段,两次考试的流水号儿是不同的。那么我们在数据库里边就能区分这是两条不同的记录,这个唯一的字段,我就把它称作叫做主键列。
1.3、第三范式:关联性
第三范式也是我们必须要满足的范式,当我们满足了第三范式,意味着同时满足了第一和第二范式,第三范式讲的是关联性,每个字段都必须与主键字段产生直接的关系,非主键字段之间是不能产生直接依赖的。
比如说,有一张表爸爸字段的值叫做陈华,儿子字段的值叫做陈浩,女儿的这个字段的值叫做陈婷婷。如果我拿爸爸字段作为主键,那么儿子字段还有女儿字段,都是依赖于爸爸这个字段的,但是后面两个字段,可就违反了第三范式。女儿的玩具和女儿的衣服是依赖于女儿这个字段的,并不依赖于爸爸这个字段,所以说这张表儿的设计是违反了第三范式。
那么符合第三范式的数据表儿应该这么去设计,原来的一张表儿,应该拆分成两张表儿去设计。比如说爸爸字段,儿子字段,还有女儿字段3个字段组成一张数据表,儿子和女儿字段是依赖于爸爸这个主键字段的。然后再往下就是女儿的玩具,女儿的衣服,还有女儿字段组成另外一张表,那么玩具也好,还是衣服也好,都是依赖于女儿字段的,这样子,两张数据表的设计都是符合第三范式的。
第三范式告诉我们,不相关的字段要拆分到其他的数据表儿里边,表和表之间是可以保持关系的
例如说部门儿信息和员工信息就不应该保存在一张表里边,于是我就定义了部门表还有员工表,部门表,有编号,部门名称,还有电话3个字段组成,后两个字段都是依赖于主键这个字段的,那么员工表有编号、姓名、性别,还有入职日期这样的字段来组成的,那么如果说,想把这个员工还有部门关联在一起的话,因为每一个员工都有自己隶属的部门,那我可以给员工表加上一个新的字段,这个字段就是部门编号,比如说陈浩这个人,他的这个隶属部门儿就是10部门,也就是财务部,这样子就算是我给这个员工表加上了一个部门编号的字段,那你可以想象部门编号字段是不是也依赖于这个员工编号的这个主键字段字段。
二、MySql的字段约束
mysql的这个字段约束一共是有四种,这四种分别是主键约束,非空约束,唯一约束,还有外键约束
|----------|-------------|----------------|
| 约束名称 | 关键字 | 描述 |
| 主键约束 | PRIMARY KWY | 字段值唯一,且不能为NULL |
| 非空约束 | NOT NULL | 字段值不能为NULL |
| 唯一约束 | UNIQUE | 字段值唯一,且可以为NULL |
| 外键约束 | FOREIGN KEY | 保持关联数据的逻辑性 |
2.1 主键约束
主键约束既要求字段不能有null值,又要求数据唯一。mysql操作数字的速度远远超过了字符串,如果我们用数字类型的字段作为主键写入数据的时候,数据库就能非常快速的判断出主键值与已有记录的主键值是否重复。而且拿主键作为检索条件的速度,也是非常快的,所以说我们都会用数字类型作为主键,如果我们自己懒得给记录规定主键值,那么就可以让数据库自动去生成主键值,其实这个原理就是一个计数器而已,在创建数据表儿的时候给主键字段后面加上auto_increment,这样子我们在插入数据的时候就可以不用给主键值了,那么主键值的生成就交给数据库去完成了,那么数据库就是一个计数器。比如说写入第一条数据的时候,那我给这个主键值附上一,第二条数据的话,那就是二,以此类推。
2.2 非空约束
我们在创建数据表的时候,哪一个字段要求有这个非空的数据,那你就在这个字段的后面加上not null就行了,在not null后面儿加上了一个default关键字files,什么意思,就是说我要求非空的时候,你在这个married字段里边填写的什么样的这个数据,这是你的自由,但是如果你不填的话,我又不想为空,怎么办?那我就加上一个默认值的这么一个要求。default后面儿写上了一个false,因为这个字段的类型是布尔,所以说,这个布尔的值只有true和false。这个字段的值,如果你不写的话,那没关系,它不是null,那么我们用files作为这个默认值保存到这个字段里边。
2.3 唯一约束
添加唯一约束也非常的简单,就是在字段后面加上unique这个关键字就行了
接下来我用一个SQL语句演示一下三种约束的使用,比如说create table,创建一个数据表,叫做teacher,然后在写字段之前我要说一下这个表儿的名字,建议各位同学给这个表名前面加上一个前缀儿,就是t_,为什么这么做?是有原因的,在数据库里边有些表儿是真实存在的,有些表并不存在是虚拟表,那这种虚拟表在数据库里边把它叫做while,叫视图的意思。所以说我给这个表名前面加上一个t_或者tb_,就代表说这是一个真实的数据表。如果说这个前缀是v或者vw下划线,那就代表说这个东西是一个虚拟的表示视图,是这个意思
比如说这个id字段是int类型的,然后是unsign的,是无符号的,然后是primary key。希望主键的值是自动生成的,所以加上auto increment,然后再往下就是name这个字段,老师是有名字的类型儿是varchar,差的字符儿最多是20个字符,然后是not null的。再往下就是联系电话,tell类型儿是char类型的,然后11个字符儿是非空的。光是非空还不行,因为电话号码儿是不能重复的,所以这里面我就加上一个unique这个关键字,代表的就是唯一,然后再往下就是婚否那个字段,married,那么婚否这个我用boolean这个类型。那booling这个类型儿会映射成TINYINT,一会儿我们看,然后它的这个值也是not null,但是有这个默认值,default这个默认值是false,默认是未婚
CREATE TABLE t_teacher(
id INT UNIQUE PRIMARY KEY AUTO_INCREMENT, # 无符号的主键,自动生成
name VARCHAR(20) NOT NULL, # 名字是20个字符,不为空
tel char(11) NOT NULL UNIQUE, # 电话是11个字符非空,不能重复
married BOOLEAN NOT NULL DEFAULT FALSE # 婚否不为空,默认未婚
);
2.4 外键约束
外键约束是用来约束多张表之间关系数据的逻辑关系。
比如说部门儿表和员工表,应该是先有部门信息,然后才有使员工的记录,按照逻辑关系的先后,我们把部门表称作是副表,把员工表儿称作是子表。如果说我们把 10 部门儿给删掉了,那么员工表中陈浩这条记录就不符合逻辑了,因为它是属于10部门儿的嘛,所以为了约束数据表之间的关联,数据的逻辑关系,这样就必须要引入外键约束了。
按照逻辑关系是员工表依赖于部门表,所以说我们创建外界约束是写在子表上的,那咱们先看一下附表的创建数据,表的sql语句,这个表叫做t_emp是部门表。字段是部门的编号,部门的名称,还有部门的电话,然后再往下,子表是员工表,叫做t_emp就是employee那个单词的缩写。然后员工的编号,员工的姓名,性别,还有是部门的这个编号,然后再往下是入职的日期,在这里面我们看到了一个新的数据类型,叫做 enum。因为我们是一个枚举的数据类型,也就是说我们可以规定好这个字段的值,然后我们在设置字段值的时候,只能是在这个规定的范围之内挑选一个,然后再往下就是这个foreign key关键字是用来规定外键约束的。
# 创建部门表
CREATE TABLE t_dept(
deptno INT UNSIGNED PRIMARY KEY,
dname VARCHAR(20) NOT NULL UNIQUE,
tel char(4) UNIQUE
)
# 创建员工表
CREATE TABLE t_emp(
empno INT UNSIGNED PRIMARY KEY,
ename VARCHAR(20) NOT NULL,
sex ENUM("男","女") NOT NULL, # 枚举性别男女
deptno INT UNSIGNED NOT NULL, # 部门编号不能为空
hiredate DATE NOT NULL, # 出生日期,不能为空
FOREIGN KEY(deptno) REFERENCES t_dept(deptno) # 外键关联部门表,通过部门编号
);
接下来我们在刚刚创建的员工表和部门表中试填写数据,并保存,如果这时点删除部门记录是删除不了的,因为已经通过部门编号关联员工表了,所以正确的这个删除的办法就是把员工删掉,然后再删除相对应的部门儿,这是可以的
部门表
员工表
外键约束的闭环问题
因为在多张表之中,如果我们建立了外键约束,一旦形成闭环结构,那么任何一张表儿的数据都是无法删除的,这非常麻烦,比如说a表作为副表,B表作为子表,副表的记录不能先删除,所以a表的数据不能删除,那么子表的数据B表可以删除,但是B表作为副表,C表作为子表,那B表的这个数据又不能删除了。C表的数据可以删除,但是以此类推,如果说F表示子表,C表示父表儿,那C表也不能删除了,然后以此类推,最后推到哪儿?推到D表这,这个D表示父表,这个a表示子表,那么D表不能删除了,所以在这里面一旦形成这个闭环结构以后,那么任何一个数据表的数据都是无法删除的。那我这个数据库就丧失了增删改查的灵活操作了,这肯定是不行的,所以说,我们在创建数据表的时候,一定是要放弃外键约束的。在真实的项目里边,这个数据表上百张都是很正常的,所以说不好哪些表之间的这个外键形成了闭环。