MySQL数据库的约束与设计解读

 更新时间:2026年01月08日 09:57:01   作者:苏小瀚  
文章介绍了数据库的约束类型,包括非空约束、默认约束、唯一约束、主键约束、外键约束和check约束,并介绍了数据库设计的三大范式:第一范式、第二范式和第三范式,还介绍了如何根据业务需求进行数据库设计和创建实体-关系图

1.数据库的约束

1.1 定义

数据库的约束是对数据库中的数据施加的规则或者条件,确保数据的准确性和可靠性。

1.2 约束类型

1.3 非空约束(not null)

not null 约束是在定义某一列属性时,设置该列的数据不能为空。

create table teacher(
	id bigint,
	name varchar(20) not null
);

这里我们就定义了name这个属性列的数据不能为空。

1.4 默认约束(default)

default 是指定一个列的属性,插入时候没有定义具体的值,此时就使用定义的默认值。z

create table teacher(
id bigint,
name varchar(20),
age bigint default 18
);

这里我们在age属性后面加上默认值18,这样我们在插入一条数据时候,没有插入age的数据,就填默认值18。

1.5 唯一约束(unique)

unique用来约束列的属性,保证列的数据不相同,具有唯一性。空值和空值之间是不算做重复的。

create table teacher(
id bigint,
name varchar(20),
age bigint default 18,
sno varchar(20) unique
);

这里我们定义sno(学号)列的属性是唯一的。

1.6 主键约束(primary key)

primary key 用来表示某一列是主键,一个表中只能有一个主键,其作用相当于unique 和 not null的结合。

一般一些具有身份表示的属性定义为主键,比如说老师的id,这里就可以id作为每个老师的身份标识。

create table teacher(
id bigint primary key,
name varchar(20),
age bigint default 18,
sno varchar(20) unique
);

这里的主键我们可以将多个属性结合作为一个主键:

create table teacher(
id bigint,
name varchar(20),
age bigint,
sno varchar(20)
primary key(id,name)
);

1.6.1 自增主键(auto_increment)

自增主键利用primary key auto_increment来定义的,针对一些整数类型的列可以自己增加大小,每次+1,每次都是在该列中最大的值的基础上+1的。

create table teacher(
    id bigint primary key auto_increment,
    name varchar(20)
);

如果一个学生表的数据很大,id为自增主键,这里将表分配到两个服务器上面,这时候自增主键就不能确保两个服务器中的数据还是唯一的,这时候我们就要利用一些算法来生成 唯一主键。

下面列举一种唯一主键的设定:

设置一个字符串id 表示唯一主键,字符串由 时间戳,机器编号,随机因子等组成字符串,然后再求出一个哈希值,就可以得到一个唯一主键了。

1.7 外键约束(foreign key)

外键约束使用的是foreign key关键字,表示两个表之间的约束关系。

这里我们创建两张表学生表和班级表:

create table student(s_id int, s_name varchar(20), s_sex varchar(20), class_id int);

insert into student values (1,'张三','男',1);
insert into student values (2,'李四','女',2);
insert into student values (3,'王五','男',3);

create table class(class_id int, class_name varchar(20));

insert into class values (1,'一班');
insert into class values (2,'二班');
insert into class values (3,'三班');

这两张表没有添加外键依赖的时候,可以正常插入,但是在学生表的class_id加上外键约束(foreign key),后,此时两个表就关联起来了。

create table student(s_id int, s_name varchar(20), s_sex varchar(20), class_id int, foreign key (class_id) references class (class_id));

外键约束:

foreign key (学生表的外键) references 班级表表名 班级表的主键;

此时的班级表约束学生表,也就是说学生表依赖(听)班级表的。

此时学生表在进行插入和修改操作的时候,就要注意class_id是否合法。不合法的话会报错。此时会先查询班级表中是否有class_id的数据。

此时班级表在进行删除和修改操作的时候,需要注意该操作是否合法,会先查询下学生表是否有使用了班级表这行要删除或者需修改操作的行

create table student(
	id int, name varchar(20), sex varchar(10), age int,
	check (age > 18),
	check (sex = '男' or sex = '女')
	);

注意:这里的外键约束所依赖的外键的列属性必须要有索引,而主键约束默认有索引。

此时有一个问题:

假设有一个商品表和一个订单表,订单表依赖于商品表的商品id。此时我们如何下架商品呢?

因为此时订单表中使用着当前的商品id,所以当前的该商品不能从商品表中直接删除,那我们可以逻辑删除,我们可以在商品表中加一列,boolean类型来判断该商品是否被下架,而订单表在创建新的订单时候where下是否这个列的属性是否表示未下架。

1.8 check约束

check约束只支持sql8版本,sql5.7不支持,sql5.7 在使用check约束时候,不会报错但是没有反应。

比如我们在创建表时候可以使用check约束:

create table student(
	id int, name varchar(20), sex varchar(10), age int,
	check (age >= 18),
	check (sex = '男' or sex = '女')
	);

此时你插入的数据年龄小于18,或者性别不符合条件就会报错。

2. 数据库设计

2.1 范式

范式是用来规范我们设计数据库的规则,一共有六大范式,但是我们只需要使用三大范式就足以:第一范式,第二范式,第三范式。

2.2 第一范式

第一范式是说:

数据库的每一列都是不可以在分割的原子数据项。

意思就是说数据库中的每一列的属性都不能再划分出来新的属性,比如说:学校这个属性就不能单独作为一个属性放在数据表中,因为学校这个还包含,学校地址,学校名称,学校电话等属性,此时我们应该使用这些划分出来的属性作为表的属性。

注意:在关系性数据库中,每一列都使用基本数据类型就可以满足第一范式了。

2.3 第二范式

第二范式是说:

在满足第一范式的基础上,还满足数据库中不能存在非关键字段对任意候选键部分函数依赖。

这里的主键可以包括一条属性,也可以包括多条属性。

  • 非关键字段:就是除了主键之外的其他属性。
  • 候选键:主键包含的属性。
  • 部分函数依赖:通过主键的一部分属性就能确定一条元素。
  • 完全函数依赖:通过主键所有属性才能确定一条元素。

第二范式就是要求数据库中不能存在 表中的某一列属性,通过主键的部分属性就推出来了。

如果不满足第二范式就可能导致数据冗余,或者插入,删除,修改异常。

当这张表主键只包含一列,就满足第二范式。

2.4 第三范式

第三范式是说:

在满足第二范式的基础上,不存在非关键字段,对于候选键存在传递依赖。

意思就是说数据表中不能存在 通过A属性能确定B属性,B属性又可以确定C属性,进而A属性能确定C属性的传递依赖。也就是说非主属性之间不能存在依赖关系。

2.5 数据库的设计过程

我们首先需要根据业务需求抽象出来具体的类:

  • 这里的类对应数据库设计中的实体,实体对应的数据库中的表。
  • 这里的类中的属性对应数据库设计中实体的属性,实体的属性对应数据库表中的列。
  • 接着找到实体与实体之间的关系,画出E-R图,
  • 最后根据E-R图创建具体的数据库。

3. 实体-关系图

3.1 E-R图的组成部分

  • 实体:相当于现实中抽象出来的类,比如:学生和课程这就是两个实体。
  • 属性:类中的属性,比如:学生id,学生姓名,课程id,课程名字等这些就是属性。
  • 关系:两个实体之间对应什么关系,比如:学生选择课程,这里的选择就是两个实体间的关系。

3.2实体与实体的关系

实体与实体的关系也就是表与表之间的关系,这里包含四种关系,一对一,一对多,多对多,没关系。

3.2.1 一对一关系

这里的一对一关系是说两个实体之间是一个对应一个的关系,比如说:人和身份证,这里一个人对应一个身份证,而一张身份证对应一个人。

一对一关系E-R图

3.2.2 一对多关系

这里的一对多关系是两个实体之间是一个对应多的的关系,比如说,学生和班级,这里的一个学生对应一个班级,一个班级可以有多个学生(高中)。

一对多关系E-R图

3.2.3 多对多关系

这里的多对多关系是指两个实体之间是多个对应多个,比如说,学生和课程,一个学生要学习习多门课程,一门课程有多个同学学习。

3.3 创建表

接下来我们就要根据E-R图创建实体对应的表。

3.3.1 一对一关系创建表

这里我用人和身份证两个实体来创建表,这里我们可以通过在任意一个表中添加另外一个表中的关键属性就能关联两张表。

  • 人(个人id,姓名,年龄,身高,体重)
  • 身份证(身份证号,姓名,出生年月,家庭住址)

这里的两个实体,可以写成:

  • 人(个人id,姓名,年龄,身高,体重,身份证id)
  • 身份证(身份证id,身份证号,姓名,出生年月,家庭住址)

也可以写成:

  • 人(个人id,姓名,年龄,身高,体重)
  • 身份证(身份证id,身份证号,姓名,出生年月,家庭住址,个人id)

下面代码就实现了在身份证表中添加人的关键属性:

create table people (
	id int primary key, 
	name varchar(20), 
	height double, 
	weight double
	);
insert into people values (1,'张三',170,60),(2,'李四',180,70);

create table card (card_id int primary key, card_num varchar(20), people_id int);
insert into card values (1,'123456',1), (2,'13579',2);

3.3.2 一对多关系创建表

这里我用学生和班级两个实体来创建表,这里我们需要在学生这个实体中添加班级实体的关键属性来关联两张表。

  • 学生(学生id,学生姓名,性别)
  • 班级(班级id,班级名称)

我们应该写成:

  • 学生(学生id,学生姓名,性别,班级id)
  • 班级(班级id,班级名称)

下面代码是在学生表中包含班级表的关键字段建立联系,外键永远放在多的一方。

create table student(id int primary key, name varchar(20), gender varchar(20), class_id int);
insert into student values(1,'张三','男',1), (2,'李四','女',2);

create table class(class_id int, class_name varchar(20));
insert into class values(1, '一班'), (2,'二班');

3.3.3 多对多关系创建表

这里我们用学生和课程两个实体来创建表,这里我们需要重新创建一张关系表来包含两个实体的关键属性来关联两张表。

  • 学生(学生id,学生姓名,性别)
  • 课程(课程id,课程名字)

我们应该写成:

  • 学生(学生id,学生姓名,性别)
  • 课程(课程id,课程名字)
  • 选课表(学生id,课程id)

下面是创建的选课表将学生和课程两个表关联起来。

create table student(id int primary key, name varchar(20), gender varchar(20));
insert into student values(1,'张三','男'), (2,'李四','女');

create table course(course_id int primary key, course_name varchar(20));
insert into course values(1,'软件工程'), (2,'高等数学'), (3,'线性代数');

create table chocourse(id int, s_id int, c_id int, foreign key (s_id) references student(id), foreign key (c_id) references course(course_id));
insert into chocourse values(1,1,1), (2,1,2), (3,2,2),(4,2,3);

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 关于Mysql中ON与Where区别问题详解

    关于Mysql中ON与Where区别问题详解

    在编写SQL脚本中,多表连接查询操作需要使用到on和where条件,但是经常会混淆两者的用法,从而造成取数错误,下面这篇文章主要给大家介绍了关于Mysql中ON与Where区别问题的相关资料,需要的朋友可以参考下
    2022-02-02
  • 浅谈MySql 视图、触发器以及存储过程

    浅谈MySql 视图、触发器以及存储过程

    这篇文章主要介绍了MySql 视图、触发器以及存储过程的的相关资料,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-06-06
  • MySql数据库之alter表的SQL语句集合

    MySql数据库之alter表的SQL语句集合

    mysql之alter表的SQL语句集合,包括增加、修改、删除字段,重命名表,添加、删除主键等。本文给大家介绍MySql数据库之alter表的SQL语句集合,感兴趣的朋友一起学习吧
    2016-04-04
  • asp.net 将图片上传到mysql数据库的方法

    asp.net 将图片上传到mysql数据库的方法

    图片通过asp.net上传到mysql数据库的方法
    2009-06-06
  • mysql幻读详解实例以及解决办法

    mysql幻读详解实例以及解决办法

    MySQL中的幻读只有在读的时候才会发生,读这里特指SELECT操作,下面这篇文章主要给大家介绍了关于mysql幻读详解实例以及解决办法的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2022-06-06
  • Mysql中FIND_IN_SET()和IN区别简析

    Mysql中FIND_IN_SET()和IN区别简析

    这篇文章主要介绍了Mysql中FIND_IN_SET()和IN区别简析,设计实例代码,具有一定参考价值。需要的朋友可以了解。
    2017-10-10
  • ERROR 1862 (HY000): Your password has expired. To log in you must change it using a .....

    ERROR 1862 (HY000): Your password has expired. To log in you

    当你在安装 MySQL过程中,通过mysqld --initialize 初始化 mysql 操作后,生成临时密码后,没有直接进行 MySQL连接,中途重启服务或者重启机器等,导致密码失效问题,怎么处理呢,感兴趣的朋友一起看看吧
    2019-11-11
  • mysql开启慢查询(EXPLAIN SQL语句使用介绍)

    mysql开启慢查询(EXPLAIN SQL语句使用介绍)

    这篇文章主要介绍了mysql开启慢查询 EXPLAIN SQL语句,需要的朋友可以参考下
    2018-01-01
  • MySQL控制流函数(-if ,elseif,else,case...when)

    MySQL控制流函数(-if ,elseif,else,case...when)

    这篇文章主要介绍了MySQL控制流函数(-if ,elseif,else,case...when),文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下
    2022-07-07
  • MySQL关于sql_mode解析与设置讲解

    MySQL关于sql_mode解析与设置讲解

    今天小编就为大家分享一篇关于MySQL关于sql_mode解析与设置讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03

最新评论