目录
[1、 NOT NULL - 非空约束](#1、 NOT NULL - 非空约束)
[2、UNIQUE - 唯一约束](#2、UNIQUE - 唯一约束)
[3、DEFAULT - 默认值约束](#3、DEFAULT - 默认值约束)
[4、PRIMARY KEY - 主键约束](#4、PRIMARY KEY - 主键约束)
[5、FOREIGN KEY - 外键约束](#5、FOREIGN KEY - 外键约束)
[(一)、第一范式 1NF](#(一)、第一范式 1NF)
[(二)、第二范式 2NF](#(二)、第二范式 2NF)
[(三)、第三范式 3NF](#(三)、第三范式 3NF)
一、数据库约束
数据库约束 是关系型数据库的一个重要功能,主要作用是为了保证数据的完整性(确保数据本身是否正确,关联关系是否正确)。然而,约束一般是指定在列上的。
(一)、约束类型
|-------------|-------------------------------|
| NOT NULL | 非空约束,指示某列不能存储NULL值 |
| UNIQUE | 唯一约束,保证某列的每一行必须有唯一的值 |
| DEFAULT | 默认值约束,规定没有给列赋值时的默认值 |
| PRIMARY KEY | 主键约束,是NOT NULL和 UNIQUE 的结合 |
| FOREIGN KEY | 外键约束,保证一个表中的数据匹配另一个表中的值的参照完整性 |
| CHRCK | 保证列中的值符合指定的条件 |
1、 NOT NULL - 非空约束
NOT NULL:指定某列不能存储NULL值
①、当在定义student表中的id没有加上not null时,在添加的值中添加id的值为NULL,则添加的这一行id的值可以为NULL:

如果想要将id这一列定义成一个必填项,那么就可以使用NOT NULL约束:

NO表示当前列不能为空。
②、当向student插入id为空的数据时,数据库将会报错,提示不能写入NULL值。
当id列有值时可以正常插入

2、UNIQUE - 唯一约束
保证某列的每一行必须有唯一的值,即某列的值在整个表中不能重复
如果id这一列不加上unique约束,当插入id值相同时也是可以正常写入的。

这样写并不符合逻辑,因此在创建student表的时候,需要在id字段加上唯一约束:

那么当再次插入id相同的记录时,将会报错:

3、DEFAULT - 默认值约束
规定没有给列赋值时的默认值
当给student表中只给插入id列插入值,name列中没有插入值,会显示name为null:

当给name字段写入默认约束时,再次只插入id列的值:


在name列使用的是自定义的默认值。
👩🏻💻:当某列设置了默认约束的时候,如果不给这一列指定值时才会使用默认约束。
如果插入name为null的时候,name列会使用无名氏还是null?

从图中可以看出,用户指定的优先级要高于默认约束。
4、PRIMARY KEY - 主键约束
NOT NULL 和 UNIQUE **的结合。**确保某列(或两个列多个列的结合)有唯一标
识,有助于更容易更快速地找到表中的一个特定的记录。
上面将id设为unique时,id为空时也是可以写入的,如果将id列同时设置非空和唯一约束时,能确保id列既是唯一也是非空。

那么也可以用primary key 表示not null 和unique:

如果插入id值相同或者id为null的数据时:

写入数据时primary key约束对唯一、非空同时生效。因此主键约束是帮我们校验写入的数据是否非空且唯一,虽然这两个校验在写入数据时对效率有一定的影响,但比起不做校验来说,这个性能好是可以承担的。
(1)、auto_increment(自增类型)
**对于数据类型的主键,常搭配 auto_increment(自增类型)来使用,**数据库将自动维护主键的增长,再插入的时候会先找到最大的值,再最大值的基础上 + 1生成一个新的值,作为新一个数据行的主键值。

指定列插入数据时,也会自动生成id,作为数据行的主键:

如果写入数据时,在不指定主键列的值,用null代替,写入记录可以插入成功吗?

这里的null,并不是将null写入数据库中,这里表示的是让数据库帮我们去处理这一列的值进行自增操作。
当不小心在写入记录时,由于各种错误原因出现报错,在下一次写入记录时,写入成功。然而,出现了主键值不连续的现象:

当insert操作时,都会先生成一个主键值,不论记录写入是否成功,主键值都会视为已使用。
(2)、复合主键:一个主键同时可以包含多个列

在唯一校验时,只有复合主键中所有的列都相同才被判定为相同

5、FOREIGN KEY - 外键约束
保证一个表中的数据匹配另一个表中的值的参照完整性
当前表中某个列的值,必须是另一张表中的主键列,或是唯一约束列的值,也就是当前表中的值在另一张表中必须存在且满足主键或者唯一约束。

①当没有在student表中的class_id(课程编号)加入外键约束,在写入一条学生记录,设置不存在的课程编号,数据是可以写入成功的:


当在student表中的class_id(课程编号)加入外键约束,在写入一条学生记录,设置不存在的课程编号,数据是不可以写入成功的:


因此,可以通过外键约束,保证数据的完整性和关系的正确性。
②、当子表student对主表class存在依赖时,是不能删除主表class中的记录的:

数据库会报一个主外键关系错误。
如果非常想要删除主表中记录,那么必须先要删除子表中对主表中想要删除记录的依赖的记录,再去删除主表中的记录:

6、CHECK
保证列中的值符合指定的条件。 对于 MySQL 数据库,对 CHECK子句进行分析,但是忽略 CHECK 子句。

二、表的设计
设计表的方法:
- 从需求中获得类,类对应到数据库中的实体,实体在数据库中表现为一张张表,类中的属性就是表中的字段;
- 确定类与类之间的关系;
- 使用SQL去创建机体的表。
在表设计的时候会遵守一些规则,一般我们这些规则称之为三大范式。
范式描述的是数据关系的模型,有一对一、一对多、多对多的关系。
范式的分类:第一范式1NF、第二范式2NF、第三范式3NF、BC范式、BCNF。
(一)、第一范式 1NF
表里的字段不可再进行拆分。
第一范式是关系型数据库的一个最基本的要求,不满足第一范式就不可以成为关系型数据库。
场景:描述一个学生的信息,设计一个学生表:
正列:学生表:
学号、姓名、学号、年龄、班级名、学校名、学校地址、学校电话
这样设计的学生表,虽然不符合数据库设计的规范,但每一列都是不可再分的,表明了一个学生和班级、学校之间的关系。
反列:学生表:
学号、姓名、学号、年龄、班级名、学校
里面的学校并没有一个数据型用来表示学校的。学校可以在分为学校名、学校地址、学校电话等。
因此,可以继续拆分在关系型数据库中绝对不允许的。
👩🏻💻:在定义表的时候,每一个字段都可以用一个数据类型表示,那么当前这个表就天然满足第一范式。
(二)、第二范式 2NF
在满足第一范式的基本上,不存在非关键字段对任意候选键的部分函数依赖(存在于复合主键的情况下)。
非关键字段:非主键字段
候选键:可以是主键、外键、没有主键时的唯一键
复合主键:一个主键可以包含多个列
场景:学生可以选修课程、课程有对应的学分、学生考试之后对每一门课程生成相应的成绩
正列:
学生表:学号、姓名、年龄
课程表:课程编号、课程名、学分
学生课程表:学号、课程编号、成绩
这样设计的表,每一张表中的非主键字段都强依赖于主键,满足第二范式。
反列:
学生课程表:学号、姓名、年龄、课程名、学分、成绩
其中姓名和年龄只依赖于学号 不依赖于课程,学分、成绩只依赖于课程名 不依赖于学生。
这种情况,存在部分函数依赖,不符合第二范式。
(部分函数依赖:对于有两个或多个字段决定一条记录的情况,如果一行数据中有些字段只与关键字段中的一个有关系)
👩🏻💻:一个表中没有复合主键(主键只有一列),那么这种表满足第二范式。
如果不满足第二范式可能会存在数据冗余、更新异常、插入异常、删除异常。
(三)、第三范式 3NF
在第二范式的基础上,不存在非关键字段,对任一候选键的传递依赖。
场景:描述学生就读哪个学院
正列:
学院表:学院编号、学院名、学院电话、学院地址
学生表:学号、姓名、年龄、学院编号
这样设计的表,每张表中的非关键字段都依赖于自己表中的主键,学生表可以通过学员编号外键与学院表建立关联关系。
反列:
学生表:学号、姓名、年龄、学院名、学院电话、学院地址
这个表存在两个实体学生、学院,其中姓名、年龄与学号强相关,学院电话、学院地址与学院名强相关。这张表出现两种强相关关系存在传递依赖,不符合第三范式。
而这两个强相关关系存在传递依赖是:学号 -> 学院名 -> 学院电话 -> 学院地址
👩🏻💻:第三范式可以解决数据冗余、更新异常、插入异常、删除异常。
(四)、实体之间的关系
实体之间的关系分为:
- 一对一关系
- 一对多关系/多对一关系
- 多对多关系
- 没有关系
1、一对一关系
场景:在登录CSDN时,一个用户只能有一个账号,一个账号只能给一个用户使用。

设计表:
①、将两个实体所有信息全都放在一张表中
user(uesr_id,name,age,phone,mail,username,password);
②、创建两张表,将两张表通过user_id做联系

2、一对多关系
场景:一个学生只能存在于一个班级,一个班级可以有多个学生

设计表:
创建学生表和班级表,将两张表做关联关系
class(class_id,name);
student(student_id,name,son,age,class_id);
蓝色标注的class_id是学生表的外键,班级表的主键,之间通过class_id建立关联关系。
3、多对多关系
场景:一个学生可以选修多门课程、一门课程也可以被多名学生选修。

设计表
创建学生表、课程表,这两张表通过中间表-学生选修课程表建立关联关系
student(student_id,name,son,age);
course(course_id,name);
student_course(id,student_id,course_id);
蓝色标注的student_id是学生选修课程表的外键,学生表的主键,紫色标注的course_id是学生选修课程表的外键,课程表的主键,学生表、课程表和学生选修课程表之间通过student_id和course_id建立关联关系。
这篇文章中,讲述了数据库的约束类型有NOT NULL -非空约束、UNIQUE -唯一约束、DEFAULT - 默认值约束、PRIMARY KEY -主键约束、FOREIGN KEY -外键约束、CHRCK;第一范式1NF、第二范式2NF、第三范式3NF、实体之间的联系有一对一、一对多、多对多的关系。