一、约束的基本概念

  1、概念:约束是作用于表中字段上的规则,用于限制储存在表中的数据

  2、目的:保证数据库中的数据的正确性,有效性和完整性

  3、分类

    • 非空约束(not null):限制该字段的数据不能为null
    • 唯一约束(unique):保证该字段的所有数据都是唯一,不重复的
    • 主键约束(primary key):主键是一行数据的唯一标识,要求非空且唯一
    • 默认约束(default):保存数据时,如果未指定该字段的值,则采用默认值
    • 检查约束(check 8.0以后的新约束):保证字段满足某一个条件
    • 外键约束(foreign key):用来让两张变的数据建立连接,保证数据的一致性和完整性

二、约束的案例实践

  需求1:创建一个表id、name、age、address、stu_num五个字段。

  需求2:id字段为主键,且设置为自动递增。

  需求3:name字段长度为10个字符并且不能为空。

  需求4:age字段要大于0并且小于150.

  需求5:address字段如果不设,默认为广州。

  需求6:stu_num唯一且不能为空。

mysql> create table stu_table(
-> id int primary key auto_increment comment "id主键",
-> name varchar(10) not null comment "姓名",
-> age int check(age>0 && age<150) comment "年龄",
-> address varchar(10) default "广州" comment "地址",
-> stu_num int not null unique comment "学号"
-> ) comment "学生表";
Query OK, 0 rows affected, 1 warning (0.03 sec)

  stu_table的表结构如下

mysql> desc stu_table;
+---------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(10) | NO | | NULL | |
| age | int | YES | | NULL | |
| address | varchar(10) | YES | | 广州 | |
| stu_num | int | NO | UNI | NULL | |
+---------+-------------+------+-----+---------+----------------+
5 rows in set (0.01 sec)

  说明:

    • Type 是字段的类型
    • Null 是是否允许为空
    • key 是标记主键,外键和唯一的
    • Default 是该字段的默认值
    • Extra 是一些额外信息的展示

  验证1:添加一组正常数据

mysql> insert into stu_table (name, age, address, stu_num) values ("张三", 18, "深圳",10001);
Query OK, 1 row affected (0.00 sec) mysql> select * from stu_table;
+----+--------+------+---------+---------+
| id | name | age | address | stu_num |
+----+--------+------+---------+---------+
| 1 | 张三 | 18 | 深圳 | 10001 |
+----+--------+------+---------+---------+
1 row in set (0.00 sec)

  说明1:各个字段都复合各个字段的要求,添加正常没有问题

  验证2:添加一个name 超过10位的异常数据

mysql> insert into stu_table (name, age, address, stu_num) values ("ABCDEFGHIJK", 18, "深圳",10002);
ERROR 1406 (22001): Data too long for column 'name' at row 1

  说明2:直接报错,提示 name  data too long 太长了

  验证3:验证age 大于150的异常情况

mysql> insert into stu_table (name, age, address, stu_num) values ("李四", 152, "深圳",10003);
ERROR 3819 (HY000): Check constraint 'stu_table_chk_1' is violated.

  说明3:这里提示了一个验证错误

  验证4:验证address不填写,默认值的设置

mysql> insert into stu_table (name, age, stu_num) values ("李四", 19,10002);
Query OK, 1 row affected (0.01 sec) mysql> select * from stu_table;
+----+--------+------+---------+---------+
| id | name | age | address | stu_num |
+----+--------+------+---------+---------+
| 1 | 张三 | 18 | 深圳 | 10001 |
| 2 | 李四 | 19 | 广州 | 10002 |
+----+--------+------+---------+---------+
2 rows in set (0.00 sec)

  说明4:在上面的insert 语句中只设置了name,age,stu_num三个字段,所以adderss就自动设置了默认值广州

  验证5:验证stu_num字段的唯一性

mysql> insert into stu_table (name, age, address, stu_num) values ("王五", 21, "上海",10002);
ERROR 1062 (23000): Duplicate entry '10002' for key 'stu_table.stu_num'

  说明5:提示10002已经重复了

三、外键约束介绍

  1、什么是外键

    • 首先外键是表中一个字段
    • 外键是两张表之间的纽带
    • 设置外键的表称之为子表,外键对应的表称之为父表

  2、外键的介绍

    

    说明1:《学生表》和《辅导员》表示两张相互独立的表。

    说明2:在《学生表》中的辅导员编号,和《辅导员表》中的辅导员编号是一一对应的

    说明3:这种情况下就可以通过辅导员编号这个字段将《学生表》和《辅导员表》联系起来了

    说明4:这是辅导员编号字段,就符合设置为外键的条件

    说明5:如果将《学生表》中的辅导员编号字段设置为外键,则《学生表》为子表,《辅导员表》为父表

    说明6:外键在父表中是唯一,不可重复的。

  3、多外键展示

    

    说明1:通过上图发现《学生表》中的班级id和《班级表》中的班级id也存在一一对应的关系

    说明2:班级id也符合设置外键的标准。

    说明3:例如:辅导员编号,班级id都符合外键的设置标准,所以一个表中可以有多个外键,但是每个外键对应不同的表

  4、不符合外键的展示

    

    说明1:在《学生表》班级评级字段和《班级考核与平级对照表》中的班级平级字段也存在着关系。

    说明2:但是这个班级评级字段就不存在外键的特征,因为班级评级在《班级考核与评级对照表》中不是惟一的。

    说明3:在子表中的四星,对应父表中有三种情况这样就会出现子表中的四星到底对应父表的哪一个四星的情况。

四、外键约束展示

  1、原始数据:student表结构及其数据

mysql> select * from student;
+----+----------+------------+-------+
| id | stu_name | teacher_id | score |
+----+----------+------------+-------+
| 1 | stu1 | 1 | 98 |
| 2 | stu2 | 1 | 88 |
| 3 | stu3 | 2 | 79 |
| 4 | stu4 | 2 | 97 |
| 5 | stu5 | 3 | 93 |
| 6 | stu6 | 3 | 86 |
+----+----------+------------+-------+
6 rows in set (0.00 sec)

  2、原始数据:teacher表结构及其数据

mysql> select * from teacher;
+------------+--------------+
| id | teacher_name |
+------------+--------------+
| 1 | 张三 |
| 2 | 李四 |
| 3 | 王五 |
+------------+--------------+
3 rows in set (0.00 sec)

  3、添加外键的语法

alter table 表名 add constraint 外键名称 foreign key (外键字段名) references 父表 (父表字段)on update 更新行为 on delete 删除行为

    说明1:alter table 是DML语法,修改表的意思,在之前的文章中已经介绍过

    说明2:add constraint 是添加约束的意思

    说明3:foreign key 是外键约束的关键字

    说明4:references 后面跟上父表和父表中字段

  4、需求:给student表中的teacher_id设置为teacher表的外键,并且对应id字段的数据

mysql> alter table student add constraint fk_teacher foreign key (teacher_id) references teacher (id);
Query OK, 6 rows affected (0.22 sec)
Records: 6 Duplicates: 0 Warnings: 0

    说明1:外键一旦设置成功,将会保持子表和父表的数据一致性和完整性。

    说明2:这个时候,如果我删除《teacher》表中的id=1的张三老师,就会出错,因为,如果张三在《teacher》表中删除了,则在《student》中的辅导员编号这列数据就找不到对应的值

    说明3:从而这样就破坏了数据的完整性和一致性

mysql> delete from teacher where id=1;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`mysql_test`.`student`, CONSTRAINT `fk_teacher` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`id`))

    说明1:这个时候就会提示,不能删除或者修改父表中的数据,因为有外键存在

  5、外键数据的更新和删除行为

    • no action:当在父表中删除/更新对应记录时,首先检查该记录是否有对应的外键,如果有则不允许删除/更新(与restrict一致)
    • restrict:当在父表中删除/更新对应记录时,首先检查该记录是否有对应的外键,如果有则不允许删除/更新(与 no action一致)
    • cascade:当在父表中删除/更新对应记录时,首先检查该记录是否有对应的外键,如果有,则也删除/更新外键在子表中的记录
    • set null:当在父表中删除/更新对应记录时,首先检查该记录是否有对应的外键,如果有则设置子表中该外键的值为null,这就要求该外键记录允许null
    • set default:父表有变更时,子表将外键列设置成一个默认的值(Innodb不支持)

  6、重新创建《student》和《teacher》表并添加外键

mysql> select * from student;
+----+----------+------------+-------+
| id | stu_name | teacher_id | score |
+----+----------+------------+-------+
| 1 | stu1 | 1 | 98 |
| 2 | stu2 | 1 | 88 |
| 3 | stu3 | 2 | 79 |
| 4 | stu4 | 2 | 97 |
| 5 | stu5 | 3 | 93 |
| 6 | stu6 | 3 | 86 |
+----+----------+------------+-------+
6 rows in set (0.00 sec) mysql> select * from teacher;
+----+--------------+
| id | teacher_name |
+----+--------------+
| 1 | 张三 |
| 2 | 李四 |
| 3 | 王五 |
+----+--------------+
3 rows in set (0.00 sec) mysql> alter table student add constraint fk_teacher foreign key (teacher_id) references teacher(id) on update cascade on delete cascade;
Query OK, 6 rows affected (0.05 sec)
Records: 6 Duplicates: 0 Warnings: 0

  7、验证cascade级联行为

    验证1:我修改《teacher》表中id=1的数据改为id=4

mysql> update teacher set id=4 where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from teacher;
+----+--------------+
| id | teacher_name |
+----+--------------+
| 2 | 李四 |
| 3 | 王五 |
| 4 | 张三 |
+----+--------------+
3 rows in set (0.01 sec) mysql> select * from student;
+----+----------+------------+-------+
| id | stu_name | teacher_id | score |
+----+----------+------------+-------+
| 1 | stu1 | 4 | 98 |
| 2 | stu2 | 4 | 88 |
| 3 | stu3 | 2 | 79 |
| 4 | stu4 | 2 | 97 |
| 5 | stu5 | 3 | 93 |
| 6 | stu6 | 3 | 86 |
+----+----------+------------+-------+
6 rows in set (0.00 sec)

    说明1:这个时候我们会发现,当我修改了《teacher》表中辅导员编号的id字段是,在《student》表中teacher_id 原本等于1的也都改为了4,这就是cascade的作用

    验证2:cascade的删除行为

mysql> select * from teacher;
+----+--------------+
| id | teacher_name |
+----+--------------+
| 2 | 李四 |
| 3 | 王五 |
+----+--------------+
2 rows in set (0.00 sec) mysql> select * from student;
+----+----------+------------+-------+
| id | stu_name | teacher_id | score |
+----+----------+------------+-------+
| 3 | stu3 | 2 | 79 |
| 4 | stu4 | 2 | 97 |
| 5 | stu5 | 3 | 93 |
| 6 | stu6 | 3 | 86 |
+----+----------+------------+-------+
4 rows in set (0.00 sec)

    说明2:和更新一样,cascade的删除也是级联的。

  8、验证set null的更新和删除行为

    需求1:同样先删除《student》和《teacher》表然后重新建立新的表,重新建立外键约束测试

mysql> select * from teacher;
+----+--------------+
| id | teacher_name |
+----+--------------+
| 1 | 张三 |
| 2 | 李四 |
| 3 | 王五 |
+----+--------------+
3 rows in set (0.00 sec) mysql> select * from student;
+----+----------+------------+-------+
| id | stu_name | teacher_id | score |
+----+----------+------------+-------+
| 1 | stu1 | 1 | 98 |
| 2 | stu2 | 1 | 88 |
| 3 | stu3 | 2 | 79 |
| 4 | stu4 | 2 | 97 |
| 5 | stu5 | 3 | 93 |
| 6 | stu6 | 3 | 86 |
+----+----------+------------+-------+
6 rows in set (0.00 sec) mysql> alter table student add constraint fk_teacher foreign key (teacher_id) references teacher(id) on update set null on delete set null;
Query OK, 6 rows affected (0.04 sec)
Records: 6 Duplicates: 0 Warnings: 0

    验证1:更新《teacher》表中id=1的数据,改为id=4

mysql> update teacher set id=4 where id=1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from teacher;
+----+--------------+
| id | teacher_name |
+----+--------------+
| 2 | 李四 |
| 3 | 王五 |
| 4 | 张三 |
+----+--------------+
3 rows in set (0.00 sec) mysql> select * from student;
+----+----------+------------+-------+
| id | stu_name | teacher_id | score |
+----+----------+------------+-------+
| 1 | stu1 | NULL | 98 |
| 2 | stu2 | NULL | 88 |
| 3 | stu3 | 2 | 79 |
| 4 | stu4 | 2 | 97 |
| 5 | stu5 | 3 | 93 |
| 6 | stu6 | 3 | 86 |
+----+----------+------------+-------+
6 rows in set (0.01 sec)

    说明1:对应更新的数据都改为了null

    验证2:删除《teacher》表中id=2的数据

mysql> delete from teacher where id = 2;
Query OK, 1 row affected (0.01 sec) mysql> select * from teacher;
+----+--------------+
| id | teacher_name |
+----+--------------+
| 3 | 王五 |
| 4 | 张三 |
+----+--------------+
2 rows in set (0.00 sec) mysql> select * from student;
+----+----------+------------+-------+
| id | stu_name | teacher_id | score |
+----+----------+------------+-------+
| 1 | stu1 | NULL | 98 |
| 2 | stu2 | NULL | 88 |
| 3 | stu3 | NULL | 79 |
| 4 | stu4 | NULL | 97 |
| 5 | stu5 | 3 | 93 |
| 6 | stu6 | 3 | 86 |
+----+----------+------------+-------+
6 rows in set (0.00 sec)

    说明1:当删除数据的时候,子表中对应的外键数据也会变成了null

五、删除外键约束

  1、删除外键的语法

alter table 表名 drop foreign key 外键名称;
mysql> alter table student drop foreign key fk_teacher;
Query OK, 0 rows affected (0.05 sec)
Records: 0 Duplicates: 0 Warnings: 0

  2、删除外键后,数据一致性和完整性的验证

mysql> delete from teacher where id=1;
Query OK, 1 row affected (0.01 sec) mysql> select * from teacher;
+----+--------------+
| id | teacher_name |
+----+--------------+
| 2 | 李四 |
| 3 | 王五 |
+----+--------------+
2 rows in set (0.00 sec)

    说明1:这个时候就可以在《teacher》表中删除id=1的张三老师了,但是这样《student》表和《teacher》表的数据的一致性就破坏了

    

Mysql基础7-约束的更多相关文章

  1. 总结: MySQL(基础,字段约束,索引,外键,存储过程,事务)操作语法

    1. 显示数据库列表 show databases; # 查看当前所有数据库 show databases \G   #以行的方式显示 2. 在命令行中,执行sql语句 mysql -e 'show ...

  2. mysql基础之约束

    约束的目的: 1.约束保证数据的完整性和一致性. 2.约束分为表级约束 和 列级 约束.(针对约束字段的数目的多少来确定的) 3.约束类型包括 not null (非空约束) primary key( ...

  3. MySQL基础(三)——约束

    MySQL基础(三)--约束 约束是在表上强制执行的数据校验规则,主要用于维护表中数据的完整性以及当数据之间有以来关系时,保护相关的数据不会被删除. 根据约束对列的限制,可以划分为:单列约束(只约束一 ...

  4. MySQL基础(6) | check约束

    MySQL基础(6) | check约束 前言 在一些情况下,我们需要字段在指定范围的输入, 例如:性别只能输入 '男'或者'女',余额只能大于0等条件, 我们除了在程序上控制以外,我们还能使用 CH ...

  5. Mysql基础代码(不断完善中)

    Mysql基础代码,不断完善中~ /* 启动MySQL */ net start mysql /* 连接与断开服务器 */ mysql -h 地址 -P 端口 -u 用户名 -p 密码 /* 跳过权限 ...

  6. MYSQL基础操作

    MYSQL基础操作 [TOC] 1.基本定义 1.1.关系型数据库系统 关系型数据库系统是建立在关系模型上的数据库系统 什么是关系模型呢? 1.数据结构可以规定,同类数据结构一致,就是一个二维的表格 ...

  7. mysql 基础篇5(mysql语法---数据)

    6 增删改数据 -- ********一.增删改数据********* --- -- 1.1 增加数据 -- 插入所有字段.一定依次按顺序插入 INSERT INTO student VALUES(1 ...

  8. MySQL基础(二)——DDL语句

    MySQL基础(二)--DDL语句 1.什么是DDL语句,以及DDL语句的作用 DDL语句时操作数据库对象的语句,这些操作包括create.drop.alter(创建.删除.修改)数据库对象. 2.基 ...

  9. MYSQL基础笔记(二)-SQL基本操作

    SQL基本操作 基本操作:CRUD,增删改查 将SQL的基本操作根据操作对象进行分类: 1.库操作 2.表操作 3.数据操作 库操作: 对数据库的增删改查 新增数据库: 基本语法: Create da ...

  10. MYSQL基础笔记(一)

    关系型数据库概念: 1.什么是关系型数据库? 关系型数据库:是一种建立在关系模型(数学模型)上的数据库 关系模型:一种所谓建立在关系上的模型. 关系模型包含三个方面: 1.数据结构:数据存储的问题,二 ...

随机推荐

  1. 25-tree shaking(树摇)

    const { resolve } = require('path'); const MiniCssExtractPlugin = require('mini-css-extract-plugin') ...

  2. maven下载和配置信息

    1. 下载maven: https://maven.apache.org/ 2. 进入官网点击 Download 3. 最新版直接下载 .tar.gz 格式linux系统 .zip windows系统 ...

  3. PTA 4-6次总结

    (1)前言: 04:这次题目集主要学习了:使用LinkedHashSet删除arraylist中的重复数据,封装,了解Scanner类中nextLine()等方法.String类中split()等方法 ...

  4. SpringBoot如何自定义一个starter

    SpringBoot starter,大家应该在平常写项目中应该非常熟悉,很多依赖都会提供集成SpringBoot的依赖,这样我们用起来就非常顺手,开箱就能用,那如何自定义一个starter呢? Sp ...

  5. 自定义alert、confirm、prompt的vue组件

    Prompt.vue组件 说明: 通过props定制定制的Prompt,可选值 mode 默认值:prompt, 其他模式:confirm.message(简单的提示,可设置提示显示时间,类似aler ...

  6. (数据科学学习手札152)geopandas 0.13版本更新内容一览

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 大家好我是费老师,昨天晚上geopandas正式 ...

  7. BS系统自动更新的实现

    背景: 我公司做的考试系统(基于java开发的BS系统)是卖给学校的,随着客户数量增多,日常版本升级.远程维护工作占了程序员很多时间,遂考虑实现系统自动化更新. 要解决的问题及解决方案: 1.什么时候 ...

  8. 2020-09-13:判断一个正整数是a的b次方,a和b是整数,并且大于等于2,如何求解?

    福哥答案2020-09-13: 首先确定b的范围,b的范围一定在[2,logN]里.然后遍历b,求a的范围,如果范围长度等于0,说明这个正整数是a的b次方.1.遍历b范围.二分法求a,a初始范围是[2 ...

  9. 使用 Django 集成 vue 到一个服务器上,还是 Django 和 vue 分开部署

    Django+Vue 的项目,实际部署的时候,使用 Django 集成 vue 到一个服务器上,还是 Django 和 vue 分开部署? 目前在架构选择,基本上定了 Django + Vue 但是实 ...

  10. 如何在Docker Compose中限制容器的CPU和内存使用?

    最近我在使用开源统计Umami过程中,发现CPU和内存经常占满,导致其它服务都不能正常使用.Umami我使用的docker-compose进行部署,于是打算使用docker-compose限制下容器的 ...