【MySQL】表的约束

【MySQL】表的约束

前言

​ 对于表来说,真正约束字段的是数据类型,但是数据类型约束很单一,我们需要有一些额外的约束,更好的保证数据的合法性,从业务逻辑角度保证数据的正确性。假如有一个字段是email,那么它会被要求是唯一的,但是单纯的数据类型是无法保证这一点的。

​ 本质上来说,约束就是通过技术手段,倒闭程序员去插入正确的数据,这样就能保证凡是插入进数据库的数据都是符合数据约束的,也就是说,约束的最终目标是保证数据的完整性和可预期性。

​ 表的约束很多,这里主要介绍如下几个: null/not null,default, comment, zerofillprimary keyauto_incrementunique keyforeign key ... references ...

正文

空属性

​ 空属性有两个值,分别是nullnot null,数据库默认字段基本都是字段为空,但是实际开发时,尽可能保证字段不为空,因为数据为空没办法参与运算。

​ 举个例子,如果创建一个班级表,包含班级名和班级所在的教室。

​ 站在正常的业务逻辑中:

  • 如果班级没有名字,你不知道你在哪个班级。
  • 如果教室名字可以为空,就不知道在哪上课。

​ 所以我们在设计数据库表的时候,一定要在表中进行限制,保证没有班级名或者教室名的数据不会插入成功。这就是所谓的“约束”。

示例:

# 创建出一个myclass表
mysql> create table if not exists myclass(
    -> class_name varchar(20) not null,
    -> class_room varchar(20) not null,
    -> other varchar(20));
Query OK, 0 rows affected (0.01 sec)

# 查看表结构
mysql> desc myclass;
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| class_name | varchar(20) | NO   |     | NULL    |       |
| class_room | varchar(20) | NO   |     | NULL    |       |
| other      | varchar(20) | YES  |     | NULL    |       |
+------------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

# 查看MySQL中记录下来的创建表的语句
mysql> show create table myclass\G
*************************** 1. row ***************************
       Table: myclass
Create Table: CREATE TABLE `myclass` (
  `class_name` varchar(20) NOT NULL,
  `class_room` varchar(20) NOT NULL,
  `other` varchar(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

# 插入一个正常的数据
mysql> insert into myclass values ('计科1班', '101教室', '算法课');
Query OK, 1 row affected (0.00 sec)

mysql> system clear;
mysql> select * from myclass;
+------------+------------+-----------+
| class_name | class_room | other     |
+------------+------------+-----------+
| 计科1班    | 101教室    | 算法课       |
+------------+------------+-----------+
1 row in set (0.00 sec)

# 插入一个只有前两个字段的数据
mysql> insert into myclass (class_name, class_room) values ('计科2班','102教室');
Query OK, 1 row affected (0.01 sec)

mysql> select * from myclass;
+------------+------------+-----------+
| class_name | class_room | other     |
+------------+------------+-----------+
| 计科1班    | 101教室      | 算法课     |
| 计科2班    | 102教室      | NULL      |
+------------+------------+-----------+
2 rows in set (0.00 sec)
# 我们可以发现没有指定的other字段具有默认值NULL

# 这里显示class_room字段没有默认值,不允许插入
mysql> insert into myclass (class_name) values ('计科2班');
ERROR 1364 (HY000): Field 'class_room' doesn't have a default value

# 这里我们想要插入一个class_room为NULL的数据,被系统拒绝了
mysql> insert into myclass (class_name, class_room) values ('计科2班', NULL);
ERROR 1048 (23000): Column 'class_room' cannot be null

​ 从上面的实验中我们可以发现,如果我们没有设置not null约束,那么默认的字段属性就是允许空值,而且如果我们插入时不给出该字段的值,系统还会给出NULL作为默认值。

默认值

​ 默认值:某一种数据会经常性的出现某个具体的值,可以在一开始就指定好,在需要真实数据的时候, 用户可以选择性的使用默认值。

示例:

# 创建一个使用了默认值约束的表
mysql> create table if not exists t1(
    -> name varchar(20) not null,
    -> age tinyint unsigned default 0,
    -> gender char(1) default '男');
Query OK, 0 rows affected (0.01 sec)

# 观察表结构
mysql> desc t1;
+--------+---------------------+------+-----+---------+-------+
| Field  | Type                | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+-------+
| name   | varchar(20)         | NO   |     | NULL    |       |
| age    | tinyint(3) unsigned | YES  |     | 0       |       |
| gender | char(1)             | YES  |     | 男      |       |
+--------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

# 查看MySQL中记录下来的创建表的语句
mysql> show create table t1 \G
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `name` varchar(20) NOT NULL,
  `age` tinyint(3) unsigned DEFAULT '0',
  `gender` char(1) DEFAULT '男'
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

# 插入只给定了name字段的数据
mysql> insert into t1 (name) values ('张三');
Query OK, 1 row affected (0.00 sec)

# 如果我们只给定一个name的值,另外两个值会直接使用默认的值
mysql> select * from t1;
+--------+------+--------+
| name   | age  | gender |
+--------+------+--------+
| 张三    |   0  | 男     |
+--------+------+--------+
1 row in set (0.00 sec)

列描述

comment,没有实际含义,专门用来描述字段,会根据表创建语句保存,用来给程序员或DBA 来进行了解。

示例:

# 创建一个简单的表并添加comment
mysql> create table t2(
    -> name varchar(20) not null comment '姓名',
    -> age tinyint unsigned default 0 comment '年龄',
    -> sex char(2) default '男' comment '性别');
Query OK, 0 rows affected (0.01 sec)

# desc 表的结构中没有列描述
mysql> desc t2;
+-------+---------------------+------+-----+---------+-------+
| Field | Type                | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+-------+
| name  | varchar(20)         | NO   |     | NULL    |       |
| age   | tinyint(3) unsigned | YES  |     | 0       |       |
| sex   | char(2)             | YES  |     | 男      |       |
+-------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

# 可以看到系统中使用和存储的创建语句中含有列描述
mysql> show create table t2 \G
*************************** 1. row ***************************
       Table: t2
Create Table: CREATE TABLE `t2` (
  `name` varchar(20) NOT NULL COMMENT '姓名',
  `age` tinyint(3) unsigned DEFAULT '0' COMMENT '年龄',
  `sex` char(2) DEFAULT '男' COMMENT '性别'
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

​ 这是一个软性的约束,当我们看见列描述时会规范到我们进行插入数据的行为。

zerofill

zerofill可以对表中存储的整数类型列进行格式化输出,如果对应列数据没有达到数字类型后面括号的位数,那么带了zerofill的数据就会在前面补上0直到位数达到括号中的位数。

示例:

# 首先创建一个这样的表
mysql> show create table t3 \G
*************************** 1. row ***************************
       Table: t3
Create Table: CREATE TABLE `t3` (
  `a` int(4) unsigned zerofill DEFAULT NULL,
  `b` int(10) unsigned DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

# 插入两个数据
mysql> insert into t3 values (1,11);
Query OK, 1 row affected (0.00 sec)

mysql> insert into t3 values (11111,111);
Query OK, 1 row affected (0.00 sec)

# 我们可以发现1的前面补了三个0,而11111的输出没有任何影响
# 也就是不够的位数会补0,位数足够就不管
mysql> select * from t3;
+-------+------+
| a     | b    |
+-------+------+
|  0001 |   11 |
| 11111 |  111 |
+-------+------+
2 rows in set (0.00 sec)

​ 此外,如果我们在创建表时没有对整数类型指定位数,系统会在执行这条语句时进行优化,填上该类型的最大位数作为括号后的值。如果没有zerofill的话,其实后面的括号是无意义的。

主键

​ 主键(primary key)用来唯一的约束该字段里面的数据,不能重复,不能为空,一张表中最多只能有一个主键约束。主键所在的列通常是整数类型。

示例:

# 创建一个带有主键的表
mysql> create table if not exists t4 (
    -> id int unsigned primary key comment '学号',
    -> name varchar(20) not null);
Query OK, 0 rows affected (0.01 sec)

# 我们可以发现我们指定的主键是默认不允许空值的,而且该列在desc中的Key显示PRI
mysql> desc t4;
+-------+------------------+------+-----+---------+-------+
| Field | Type             | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id    | int(10) unsigned | NO   | PRI | NULL    |       |
| name  | varchar(20)      | NO   |     | NULL    |       |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

# 在底层系统使用和保存下来的语句
mysql> show create table t4 \G;
*************************** 1. row ***************************
       Table: t4
Create Table: CREATE TABLE `t4` (
  `id` int(10) unsigned NOT NULL COMMENT '学号',
  `name` varchar(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

# 插入一个id为1的数据
mysql> insert into t4 values (1, '张三');
Query OK, 1 row affected (0.00 sec)
# 继续插入一个id为1的数据,发现系统拦截了这个语句
mysql> insert into t4 values (1, '李四');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
# 原因是id为1的数据已经存在了

# 对于主键属性的简单使用:
mysql> select * from t4;
+----+--------+
| id | name   |
+----+--------+
|  1 | 张三   |
|  2 | 李四   |
+----+--------+
2 rows in set (0.00 sec)

mysql> update t4 set name='王五' where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from t4;
+----+--------+
| id | name   |
+----+--------+
|  1 | 王五   |
|  2 | 李四   |
+----+--------+
2 rows in set (0.00 sec)

​ 通过主键约束,我们可以保证某些列的数据组合在表中唯一存在的,这样我们就可以方便的通过主键锁定某一数据并进行后续操作。其他关于主键的命令:

# 删除主键
alter table 表名 drop primary key;

# 对上面创建的表进行主键删除
mysql> alter table t4 drop primary key;
Query OK, 2 rows affected (0.03 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> desc t4;
+-------+------------------+------+-----+---------+-------+
| Field | Type             | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id    | int(10) unsigned | NO   |     | NULL    |       |
| name  | varchar(20)      | NO   |     | NULL    |       |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

# 删除主键之后,我们可以插入id重复的数据
mysql> insert into t4 values(2,'张三');
Query OK, 1 row affected (0.00 sec)

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

# 在表没有主键的情况下设置主键:
alter table 表名 add primary key(字段列表)

# 对上面表中id列的进行主键设置:
mysql> alter table t4 add primary key(id);
ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY'
# 系统发现表中有两个id为2的数据,于是不让我们进行设置

# 那么我们首先删掉一个id为2的数据,这样就可以进行设置了
mysql> delete from t4 where name='张三';
Query OK, 1 row affected (0.01 sec)

mysql> alter table t4 add primary key(id);
Query OK, 0 rows affected (0.05 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc t4;
+-------+------------------+------+-----+---------+-------+
| Field | Type             | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id    | int(10) unsigned | NO   | PRI | NULL    |       |
| name  | varchar(20)      | NO   |     | NULL    |       |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

​ 除了单一字段作为主键以外,创建表的时候,在所有字段之后可以使用primary key(主键字段列表)来创建多个字段构成的主键,也就是复合主键。

示例:

# 创建一个两个字段作为主键的表
mysql> create table pick_course(
    -> id int unsigned comment '学生id',
    -> course_id int unsigned comment '课程id',
    -> score int unsigned comment '该学生这门课的分数',
    -> primary key(id, course_id));
Query OK, 0 rows affected (0.02 sec)
# 设置id和course_id作为主键之后,该表的一个数据中id和course_id的组合就必须是唯一的
# 也就是说,这两个字段合起来为一个主键
# 在当前的表中,这样设置主键表示一个学生不能多次选择同一门课,但是可以选择不同的课

mysql> desc pick_course;
+-----------+------------------+------+-----+---------+-------+
| Field     | Type             | Null | Key | Default | Extra |
+-----------+------------------+------+-----+---------+-------+
| id        | int(10) unsigned | NO   | PRI | NULL    |       |
| course_id | int(10) unsigned | NO   | PRI | NULL    |       |
| score     | int(10) unsigned | YES  |     | NULL    |       |
+-----------+------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
# 插入数据:
mysql> insert into pick_course values (1, 1, 10);
Query OK, 1 row affected (0.01 sec)

mysql> insert into pick_course values (1, 2, 10);
Query OK, 1 row affected (0.00 sec)

mysql> insert into pick_course values (1, 1, 9);
ERROR 1062 (23000): Duplicate entry '1-1' for key 'PRIMARY'

# 不允许插入前两个数据同为‘1 1’的数据
mysql> select * from pick_course;
+----+-----------+-------+
| id | course_id | score |
+----+-----------+-------+
|  1 |         1 |    10 |
|  1 |         2 |    10 |
+----+-----------+-------+
2 rows in set (0.00 sec)

自增长

​ 自增长(auto_increment):当对应的字段不给值,会自动的被系统触发,系统会从当前字段中已经有的最大值 +1操作,得到一个新的不同的值。通常和主键搭配使用,作为逻辑主键。

自增长的特点:

  • 任何一个字段要做自增长,前提是本身是一个索引(key一栏有值)
  • 自增长字段必须是整数
  • 一张表最多只能有一个自增长

示例:

mysql> create table t5 ( id int unsigned primary key auto_increment, name varchar(20) not null);
Query OK, 0 rows affected (0.02 sec)

mysql> desc t5;
+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(20)      | NO   |     | NULL    |                |
+-------+------------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

# 插入两个只给出name的数据
mysql> insert into t5 (name) values ('张三'),('李四');
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from t5;
+----+--------+
| id | name   |
+----+--------+
|  1 | 张三   |
|  2 | 李四   |
+----+--------+
2 rows in set (0.00 sec)

# 插入一个给出id的数据和一个不给出id的数据:
mysql> insert into t5 (id, name) values (100,'王五');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t5 (name) values ('赵六');
Query OK, 1 row affected (0.00 sec)

mysql> select * from t5;
+-----+--------+
| id  | name   |
+-----+--------+
|   1 | 张三   |
|   2 | 李四   |
| 100 | 王五   |
| 101 | 赵六   |
+-----+--------+
4 rows in set (0.00 sec)
# 我们发现后面的数据按照最新插入的id数据自动带入+1的id

# 数据库中存储的表创建语句:
mysql> show create table t5 \G
*************************** 1. row ***************************
       Table: t5
Create Table: CREATE TABLE `t5` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=102 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
# 我们发现其中有一个数值102AUTO_INCREMENT=102,这表明系统中会自己维护一个数值每次插入都进行+1,除此之外,我们在创建表时也可以自定义这个值,方法就是按照上面的这种格式进行自定义。

唯一键

​ 一张表中有往往有很多字段需要唯一性,数据不能重复,但是一张表中只能有一个主键:唯一键就可以 解决表中有多个字段需要唯一性约束的问题。

​ 唯一键的本质和主键差不多,唯一键允许为空,而且可以多个为空,空字段不做唯一性比较。

​ 关于唯一键和主键的区别, 我们可以简单理解成,主键更多的是标识数据在表中的唯一性的。而唯一键更多的是保证在业务上,数据的该字段不要和别的信息出现重复。

示例:

mysql> create table t6(
    -> id int unsigned primary key,
    -> telephone varchar(20) unique key,
    -> name varchar(20) not null);
Query OK, 0 rows affected (0.01 sec)

mysql> show create table t6 \G
*************************** 1. row ***************************
       Table: t6
Create Table: CREATE TABLE `t6` (
  `id` int(10) unsigned NOT NULL,
  `telephone` varchar(20) DEFAULT NULL,
  `name` varchar(20) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `telephone` (`telephone`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> desc t6;
+-----------+------------------+------+-----+---------+-------+
| Field     | Type             | Null | Key | Default | Extra |
+-----------+------------------+------+-----+---------+-------+
| id        | int(10) unsigned | NO   | PRI | NULL    |       |
| telephone | varchar(20)      | YES  | UNI | NULL    |       |
| name      | varchar(20)      | NO   |     | NULL    |       |
+-----------+------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)


mysql> insert into t6 values(1, '1234', '张三');
Query OK, 1 row affected (0.00 sec)
# 唯一键默认可以为空
mysql> insert into t6 values(2, null , '李四');
Query OK, 1 row affected (0.00 sec)
# 唯一键保证了表中的数据在该字段的唯一性
mysql> insert into t6 values(3, '1234' , '王五');
ERROR 1062 (23000): Duplicate entry '1234' for key 'telephone'

mysql> select * from t6;
+----+-----------+--------+
| id | telephone | name   |
+----+-----------+--------+
|  1 | 1234      | 张三   |
|  2 | NULL      | 李四   |
+----+-----------+--------+
2 rows in set (0.00 sec)

外键

​ 外键用于定义主表和从表之间的关系:外键约束主要定义在从表上,主表则必须是有主键约束或unique 约束。当定义外键后,要求外键列数据必须在主表的主键列存在或为null。

# 语法, 在从表的定义时使用
foreign key (字段名) references 主表(列)

​ 例如,班级表和学生表,其中一定有学生表依附于班级表,学生会被分成各个班,其中学生会有一个他属于哪个班级的属性,那么这时就可以使用外键,将学生表和班级表关联起来。

示例:

# 创建一个学生表
mysql> create table if not exists student(
    -> id int unsigned primary key auto_increment,
    -> name varchar(20) not null,
    -> telephone varchar(20) unique key,
    -> class_id int);
Query OK, 0 rows affected (0.02 sec)

mysql> desc student;
+-----------+------------------+------+-----+---------+----------------+
| Field     | Type             | Null | Key | Default | Extra          |
+-----------+------------------+------+-----+---------+----------------+
| id        | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| name      | varchar(20)      | NO   |     | NULL    |                |
| telephone | varchar(20)      | YES  | UNI | NULL    |                |
| class_id  | int(11)          | YES  |     | NULL    |                |
+-----------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

# 创建一个班级表
mysql> create table class(
    -> id int unsigned primary key,
    -> name varchar(20) not null);
Query OK, 0 rows affected (0.02 sec)

mysql> desc class;
+-------+------------------+------+-----+---------+-------+
| Field | Type             | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id    | int(10) unsigned | NO   | PRI | NULL    |       |
| name  | varchar(20)      | NO   |     | NULL    |       |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

# 我们现在有两个表,它们之间是有关系的,学生表中的数据的class_id字段必须和班级表中的对应字段相关联,不存在的班是不会存在学生的,如果我们想要插入一个错误的class_id的学生,系统应该拒绝,或者我们想要删除一个还有学生的班级,这也是不行的。于是我们就需要外键约束,否则单纯的这两个表直接实现上述逻辑是很麻烦的。

# 先删除原来的学生表
mysql> drop table student;
Query OK, 0 rows affected (0.01 sec)

# 所以我们现在重新定义一下student表,并加入外键:
mysql> create table if not exists student( 
    -> id int unsigned primary key auto_increment, 
    -> name varchar(20) not null,
    -> telephone varchar(20) unique key,
    -> class_id int unsigned,
    -> foreign key (class_id) references class(id)
	-> );
Query OK, 0 rows affected (0.02 sec)

mysql> desc student;
+-----------+------------------+------+-----+---------+----------------+
| Field     | Type             | Null | Key | Default | Extra          |
+-----------+------------------+------+-----+---------+----------------+
| id        | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| name      | varchar(20)      | NO   |     | NULL    |                |
| telephone | varchar(20)      | YES  | UNI | NULL    |                |
| class_id  | int(10) unsigned | YES  | MUL | NULL    |                |
+-----------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

# 现在我们正式进行实验:

# 先插入两个班
mysql> insert into class values (1,'计科1班');
Query OK, 1 row affected (0.00 sec)

mysql> insert into class values (2,'计科2班');
Query OK, 1 row affected (0.00 sec)

mysql> select * from class;
+----+------------+
| id | name       |
+----+------------+
|  1 | 计科1班    |
|  2 | 计科2班    |
+----+------------+
2 rows in set (0.00 sec)

# 插入正常的数据:
mysql> insert into student (name, telephone, class_id) values ('张三', '1234', 1);
Query OK, 1 row affected (0.00 sec)

mysql> system clear;
mysql> insert into student (name, telephone, class_id) values ('李四', '1235', 1);
Query OK, 1 row affected (0.00 sec)

mysql> insert into student (name, telephone, class_id) values ('王五', '1236', 2);
Query OK, 1 row affected (0.00 sec)

mysql> insert into student (name, telephone, class_id) values ('张三', '1237', 2);
Query OK, 1 row affected (0.01 sec)

mysql> select * from student;
+----+--------+-----------+----------+
| id | name   | telephone | class_id |
+----+--------+-----------+----------+
|  1 | 张三   | 1234      |        1 |
|  2 | 李四   | 1235      |        1 |
|  3 | 王五   | 1236      |        2 |
|  4 | 张三   | 1237      |        2 |
+----+--------+-----------+----------+
4 rows in set (0.00 sec)

# 我们这时候想要插入一个id为3的班级的学生,系统拒绝了这条语句
mysql> insert into student (name, telephone, class_id) values ('张三', '1238', 3);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`db`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`))

# 我们想要删除一个还有学生的班级(id=1),系统也拒绝了这条语句
mysql> delete from class where id=1;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`db`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`))

# 我们还可以插入一个暂时还没有分班的同学(class_id=null)
mysql> insert into student (name, telephone, class_id) values ('张三', '1238', null);
Query OK, 1 row affected (0.00 sec)

如何理解外键约束:

​ 其实对于上面的两张表,我们不创建外键约束也可以实现对应的逻辑,但是万一在插入数据时出现了错误,那么以后的操作都会出现问题。

​ 因为此时两张表在业务上是有相关性的,但是在业务上没有建立约束关系,那么由别人进行插入数据时就可能会出现失误。 解决方案就是通过外键完成的。建立外键的本质其实就是把相关性交给mysql去审核了,提前告诉mysql 表之间的约束关系,那么当用户插入不符合业务逻辑的数据的时候,mysql不允许你插入。

  • 11
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

发呆的yui~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值