有些时候,为了保证数据的完整性,我们会选择的使用外键约束,例如教师对应的表和课程表中老师的id,这种时候就要使用外键约束了。

PS:这里不考虑表结构设计,三范式与反范式等设计问题,基于MySQL8.0

语法:

constraint 外键名 foreign key 外键字段 references 主表名(关联字段) [主表记录删除时的动作] [主表记录更新时的动作]

constraint可以省略,只是用来指定外键名

例如:

CREATE TABLE test (
course_id INT (11) NOT NULL AUTO_INCREMENT,
NAME VARCHAR (30) DEFAULT NULL,
PRIMARY KEY (course_id),
CONSTRAINT cour_id_fk FOREIGN KEY (course_id) REFERENCES teacher (teacher_id)
);

或者通过alter添加:

alter table course add constraint course_id_fk foreign key (course_id) references teacher(teacher_id) on delete cascade on update cascade;

PS:关联主表的column必须是索引,如果不是索引无法添加外键约束

做个测试:

mysql> CREATE TABLE test2 (
-> course_id INT (11) NOT NULL AUTO_INCREMENT,
-> identified_no INT(18) UNIQUE,
-> NAME VARCHAR (30) DEFAULT NULL,
-> PRIMARY KEY (course_id)
-> );
Query OK, 0 rows affected (0.03 sec) mysql> CREATE TABLE test1 (
-> course_id INT (11) NOT NULL AUTO_INCREMENT,
-> identified_no INT(18) UNIQUE,
-> NAME VARCHAR (30) DEFAULT NULL,
-> PRIMARY KEY (course_id),
-> CONSTRAINT cour_id1_fk FOREIGN KEY (NAME) REFERENCES test2 (NAME)
-> );
ERROR 1822 (HY000): Failed to add the foreign key constraint. Missing index for constraint 'cour_id1_fk' in the referenced table 'test2'
mysql> drop table if exists test2;
Query OK, 0 rows affected (0.02 sec) mysql> CREATE TABLE test2 (
-> course_id INT (11) NOT NULL AUTO_INCREMENT,
-> identified_no INT(18) UNIQUE,
-> NAME VARCHAR (30) DEFAULT NULL,
-> PRIMARY KEY (course_id),
-> INDEX(NAME)
-> );
Query OK, 0 rows affected (0.03 sec) mysql> CREATE TABLE test1 (
-> course_id INT (11) NOT NULL AUTO_INCREMENT,
-> identified_no INT(18) UNIQUE,
-> NAME VARCHAR (30) DEFAULT NULL,
-> PRIMARY KEY (course_id),
-> CONSTRAINT cour_id1_fk FOREIGN KEY (NAME) REFERENCES test2 (NAME)
-> );
Query OK, 0 rows affected (0.04 sec)

结果:name列如果不是索引,无法作为外键的引用列,当我们添加name为索引,发现添加外键约束成功

外键约束的方式有四种:

1、cascade:

  级联方式,删除/更新父表的某条记录,子表中引用该值的记录会自动被删除/更新

CREATE TABLE `teacher` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1002 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
CREATE TABLE `course` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) DEFAULT NULL,
`teacher_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `course_id_fk` (`teacher_id`),
CONSTRAINT `course_id_fk` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
mysql> select * from teacher;
+------+-------+
| id | name |
+------+-------+
| 1001 | sam |
| 1002 | jesen |
+------+-------+
2 rows in set (0.00 sec) mysql> select * from course;
+----+--------+------------+
| id | name | teacher_id |
+----+--------+------------+
| 1 | 语文 | 1001 |
| 2 | 数学 | 1002 |
+----+--------+------------+
2 rows in set (0.00 sec) mysql> update teacher set id=1 where id=1001;  //更新主表的id,从表的外键值会更新
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from course;
+----+--------+------------+
| id | name | teacher_id |
+----+--------+------------+
| 1 | 语文 | 1 |
| 2 | 数学 | 1002 |
+----+--------+------------+
2 rows in set (0.00 sec) mysql> delete from teacher where id=1;  //删除主表的id,从表外键值对应的那条数据也会删除
Query OK, 1 row affected (0.00 sec) mysql> select * from course;
+----+--------+------------+
| id | name | teacher_id |
+----+--------+------------+
| 2 | 数学 | 1002 |
+----+--------+------------+
1 row in set (0.00 sec) mysql> update course set teacher_id=2 where id =1;  //不能直接更新从表的外键
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`mysql`.`course`, CONSTRAINT `course_id_fk` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)

2、set null:

  设置为null。主表主键值被更新或删除,从表的外键被设置为null。但注意,要求该外键列,没有not null属性约束。

先删除外键,后重建:

mysql> alter table course drop foreign key course_id_fk;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0 mysql> alter table course add constraint course_id_fk foreign key (teacher_id) references teacher(id) on delete set null on update set null;
Query OK, 1 row affected (0.06 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from course;
+----+--------+------------+
| id | name | teacher_id |
+----+--------+------------+
| 1 | 数学 | 1002 |
+----+--------+------------+
1 row in set (0.00 sec) mysql> update teacher set id=1001;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from course;
+----+--------+------------+
| id | name | teacher_id |
+----+--------+------------+
| 1 | 数学 | NULL |
+----+--------+------------+
1 row in set (0.00 sec)
mysql> delete from teacher ;
Query OK, 1 row affected (0.00 sec) mysql> select * from course;
+----+--------+------------+
| id | name | teacher_id |
+----+--------+------------+
| 1 | 数学 | NULL |
+----+--------+------------+
1 row in set (0.00 sec)

no action/restrict:

  禁止模式,拒绝父表删除和更新

mysql> alter table course drop foreign key course_id_fk;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0 mysql> alter table course add constraint course_id_fk foreign key (teacher_id) references teacher(id) on delete no action on update restrict;
Query OK, 1 row affected (0.06 sec)
Records: 1 Duplicates: 0 Warnings: 0 mysql> update teacher set id=10012;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`mysql`.`course`, CONSTRAINT `course_id_fk` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`id`) ON UPDATE RESTRICT) mysql> delete from teacher;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`mysql`.`course`, CONSTRAINT `course_id_fk` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`id`) ON UPDATE RESTRICT)

默认:也是禁止模式

alter table course add constraint course_id_fk foreign key (teacher_id) references teacher(id);

MySQL系列(十一)--外键约束foreign key的基本使用的更多相关文章

  1. 外键约束 foreign key

    外键约束 :保持数据一致性,完整性实现一对多关系.外键必须关联到键上面去,一般情况是,关联到另一张表的主键 (因为一个表只存一类信息.用外键来做参照,保证数据的一致性,可以减少数据冗余) ##表acr ...

  2. 关于数据库主从表、主键PRIMARY KEY 外键约束 FOREIGN KEY 约束----NOT NULL,DEFAULT,CHECK

    如果由两个列共同组成主键,而且一个子表将主键作为可为空值的外键来继承,就可能得到错误的数据.可在一个外键列中插入有效的值,但在另一个外键列中插入空值.然后,可添加一个数据表检查约束,在可为空的外键中检 ...

  3. mysql 外键(FOREIGN KEY)

    最近有开始做一个实验室管理系统,因为分了几个表进行存储·所以要维护表间的关联··研究了一下MySQL的外键. (1)只有InnoDB类型的表才可以使用外键,mysql默认是MyISAM,这种类型不支持 ...

  4. MySQL(10):实体、实体表和外键(foreign key)

    1.实体        数据库管理系统中的各种用于数据管理方便而设定的各种数据管理对象,如:数据库表.视图.存储过程等都是数据库实体.广义上讲,这些对象中所存储的数据也是数据库实体.因为它们也是确切存 ...

  5. 如何在MySQL中设置外键约束

    引用:http://blog.sina.com.cn/s/blog_53729e4601011wja.html MySql外键设置详解   (1) 外键的使用: 外键的作用,主要有两个:    一个是 ...

  6. MySQL truncate含有外键约束的条目报错

    1.报错信息: Cannot truncate a table referenced in a foreign key constraint 2.出现错误操作: truncate table a1; ...

  7. 【MySQL】MySQL进阶(外键约束、多表查询、视图、备份与恢复)

    约束 外键约束 外键约束概念 让表和表之间产生关系,从而保证数据的准确性! 建表时添加外键约束 为什么要有外键约束 -- 创建db2数据库 CREATE DATABASE db2; -- 使用db2数 ...

  8. 如何在MySQL中设置外键约束以及外键的作用

    1.外键的作用,主要有两个:     一个是让数据库自己通过外键来保证数据的完整性和一致性     一个就是能够增加ER图的可读性 2.外键的配置 1)先创建一个主表,代码如下: #创建表studen ...

  9. SET FOREIGN_KEY_CHECKS=0;在Mysql中取消外键约束。

    SET FOREIGN_KEY_CHECKS=0;在Mysql中取消外键约束.

随机推荐

  1. JavaScript - DOM相关

    DOM节点分类 ( node ) : 元素节点 ( element node ) 属性节点 ( attribute node ) 文本节点 ( text node) DOM的相关操作 : 1. 查询元 ...

  2. Windows 关闭win32 控制台

    {     fclose(pf); BOOL ret = FreeConsole(); }

  3. PouchContainer 开源版本及内部版本一致性实践

    PouchContainer 开源版本及内部版本一致性实践 为什么要做内外版本一致 对外开源是提升影响力.共建生态的有力手段.在项目对外开源的过程中,首先是将可以开源的部分抽离出来,发布一个“开源版本 ...

  4. 最大流任务调度——hdu3572二分图建图

    很简单的任务调度模板题 把一个工作完成一天的量当做是边 /* 任务调度问题最大流 因为两个任务之间是没有关系的,两天之间也是没有关系的 所以抽象成二分图 任务i在天数[si,ei]之间都连一条双向边, ...

  5. 多线程--GIL锁

    GIL 即全局解释器锁,是一个互斥锁,防止多个线程在同一时间执行python代码,因为在一个python进程中,不仅有主线程而且还有该主线程开启的子线程,还有解释器开启的垃圾回收机等解释器级别的线程. ...

  6. c语言 局部变量做返回值 问题

    一般的来说,函数是可以返回局部变量的. 局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了.因此,如果函数返回的是局部变量的值,不涉及地址,程序不会出错.但是如果返回的是局部变量的地 ...

  7. 浅析ES的_source、_all、store、index

    Elasticsearch中有大量关键概念容易混淆,对于初学者来说是噩梦: _source字段里存储了什么? index属性的作用是什么? 何时应该开启_all字段? store属性和_source字 ...

  8. tomcat下面部署多个项目

    最近需要部署多个项目,我目前所知道的两种方法,第一种是一个tomcat部署一个项目,需要布置多个tomcat就可以部署多个项目.第二种就是一个tomcat下面部署多个项目. 首先我们先来说说两种的优劣 ...

  9. 2019-5-21-Total-Commander-显示文件包含文件名扩展

    title author date CreateTime categories Total Commander 显示文件包含文件名扩展 lindexi 2019-5-21 11:37:6 +0800 ...

  10. 在 my_rootfs 中建立 Linux 目录树

    [arm@localhost my_rootfs]#mkdir bin dev etc home lib mnt proc sbin sys tmp root usr [arm@localhost m ...