外键约束(FOREIGN KEY(字段) REFERENCES 主表名(字段))

外键约束的作用:

限定某个字段的引用完整性

  • 我们之前在讲数据完整性的时候就提到过引用完整性

    • 引用完整性(eg: 员工所在的部门,在部门表中一定要能找到这个部门)

主表和从表:

主表也称之为父表,从表也称之为子表

  • 主表(父表) : 被引用的表
  • 从表(子表) : 引用别人的表
  • 我们如何区分从表和主表?
    • 我们只需要记住: 我们在"从表"中指定外键约束,那么我们就可以知道那个表是从表了,知道了哪个表是从表,那么我们也就知道了哪个表是主表了

外键约束的特点:

  1. 从表的外键列,必须引用主表的主键列或者唯一约束的列

    • 因为被参考的值(也就是被引用的值)必须是唯一的
  2. 在创建外键约束的时候,如果不给外键约束命名,默认的外键约束名不是列名,而是自动产生的一个外键名(例如: student_ibfk_1;)当然我们也可以给外键约束命名

  3. 在创建表时就指定外键约束的话,一定要先创建主表再创建从表

    • 因为如果我们是在创建表的时候创建外键约束,这个时候如果我们直接创建从表,那么由于我们还没有创建主表,这个时候我们却要在从表中引用主表,那么当然执行就会出现错误
  4. 删除表时,要先删除从表(子表),再删除主表(父表)

    • 又或者将外键约束先删除掉,约束没有了,那么怎么删都无所谓了
  5. 当主表的记录被从表参照时,主表的记录将不允许被删除,如果我们要删除数据,则要先删除从表中依赖该记录的数据,然后才可以删除主表中的数据

  6. 当"从表"中指定外键约束,并且一个表中可以有多个外键约束

  7. 从表中的外键列与主表被参照的列的列名可以不相同,但是数据类型一定是相同的,逻辑意义一致,如果类型不一样,创建子表时就会出现错误

  8. 当创建外键约束时,系统默认会在所在列上建立对应的普通索引,索引名是外键的约束名

  9. 删除外键约束后,必须手动删除对应的普通索引

那么我们如何添加外键约束?

这里添加外键约束我们还是分为两种方式

方式一: 在CREATE TABLE时添加约束

  • 注意:我们在添加外键约束的时候一般都是将外键约束设置为表级约束,因为以列级约束添加约束的时候不能指定约束名,而我们对于外键约束来讲默认的约束名不是列名,又由于我们删除外键约束的时候要指明外键约束名,因为我们的一个表中可以声明多个外键约束,所以我们就要通过外键约束名来删除外键约束,所以我们最好在创建外键约束的时候最好就指明外键约束名

这里我们通过举例说明如何在CREATE TABLE时添加约束

我们先创建主表:(如下)
CREATE TABLE dept1(
dept_id INT PRIMARY KEY,
dept_name VARCHAR(15)
);
  • 这里我们就是创建了主表(部门表)
然后这里我们创建从表:(如下)
CREATE TABLE emp1(
emp_id INT PRIMARY KEY AUTO_INCREMENT,
emp_name VARCHAR(15),
department_id INT,#表级外键约束
CONSTRAINT fk_emp1_dept_id FOREIGN KEY(department_id) REFERENCES dept1(dept_id)
);
  • 这里我们创建了从表(员工表)
  • 这里使用员工表中的department_id字段和部门表中的dept_id字段建立了外键连接,这个时候部门表就是主表,员工表就是从表
    • 这个时候要注意: 主表中被引用的字段是键列(也就是有唯一性约束或者主键约束)
  • 这里我们添加外键约束的时候通过了表级约束的方式,并使用了constraint关键字对外键约束命名为 fk_emp1_dept_id
  • references关键字的作用就是标示主表中被引用的列

那么有了外键约束之后有什么作用?

这里我们通过举例说明

INSERT INTO emp1
VALUES(1001,'tom',10);
  • 这个时候会添加失败,因为这个时候我们的主表(部门表)中还没有添加部门,那么在从表中添加数据就是添加不进去的 — 因为我们的外键约束的功能就是判断在从表中添加的数据中的外键约束字段的值一定要在主表中被引用的字段的值中找到相同值,否则就判断添加不成功
所以说我们要想在从表(员工表)中添加数据,那么就先要在主表(部门表)中添加数据,先要有部门,那么才能有这个部门的员工
INSERT INTO dept1
VALUES(10,'IT');
  • 这个时候我们就在部门表(主表)中添加了一条记录,也即是添加了10号部门,那么后面我们就可以在员工表中添加数据了,但是注意要添加的员工一定部门id都要为10
这个时候我们再执行一次添加员工的操作
INSERT INTO emp1
VALUES(1001,'tom',10);
然后这个时候我们从表(员工表)中有10号部门的员工了,那么接下来我们就不能删除主表中的id为10的部门了
DELETE FROM dept1
WHERE dept_id = 10;
  • 这个时候就会删除失败,因为我们从表中有10号部门的员工了,这个时候在主表中就不能删除10号部门了,除非先将从表中10号部门的员工删除掉,或者将外键约束删除掉

方式二 : 在ALTER TABLE时添加外键约束

首先我们先创建两个表

  1. 这里我们先创建一个部门表(主表)
CREATE TABLE dept2(
dept_id INT PRIMARY KEY,
dept_name VARCHAR(15)
);
  1. 然后这里我们再创建一个员工表(从表)
CREATE TABLE emp2(
emp_id INT PRIMARY KEY AUTO_INCREMENT,
emp_name VARCHAR(15),
department_id INT
);
  • 然后这里我们在ALTER TABLE时添加外键约束
ALTER TABLE emp2
ADD CONSTRAINT fk_emp2_dept_id FOREIGN KEY(department_id) REFERENCES dept2(dept_id);
  • 这里我们就是在员工表中使用员工表中的department_id字段和部门表中的dept_id建立了外键连接(我们的部门表中的dept_id是一个主键列(也就是添加了主键约束)),所以这里外键约束添加也会是成功的

建立了外键约束之后我们可以通过一条指定的SQL语句来查询外键约束是否添加成功

SELECT *
FROM information_schema.`TABLE_CONSTRAINTS`
WHERE table_name = 'emp2';
  • 注意: 这里的 where table_name = ‘emp2’中的’'是一对单引号,表示是字符串,也就是表名,这里时为了判断表名,显然我们就是要对字符串之间进行判断,而不是加着重号和关键字进行区分

我们还要将一件事情: 外键约束等级

  1. Cascade : 在父表上update/delete记录时,同步的update/delete子表中的匹配的记录

  2. Set null : 在父表上update/delete记录时,将子表上匹配记录的列设为null,但是要注意子表的外键列不能设置为not null

    • 如果子表外键列设置为not null,那么我们就不能使用Set null的方式,因为这个时候是冲突的,按理我们设置了Set null之后如果我们要修改或者删除主表中的记录的时候就会将从表中的对应的记录的外键列设置为null,但是这个时候我们的从表中的外键列又设置了not null,这样肯定是不行,所以当外键约束等级为Set null时,这个时候就不能将从表中的外键列设置为not null
  3. No action : 如果在子表中有和主表匹配的记录,那么就不允许对主表进行update/delete操作

  4. Restrict : 和No action是一样的

  5. Set default : 这个我们知道就行,不使用

注意: 如果没有指定外键约束等级,就相当于Restrict方式(或者说是No action的方式)
  • Restrict方式和No action方式功能是一样的

这里我们通过一个例子来理解如果给外键约束指定约束等级

eg: 这里我们设置为on update on delete setnull

  1. 我们也还是先创建主表(部门表)
CREATE TABLE dept3(
d_id INT PRIMARY KEY,
d_name VARCHAR(50)
);
  1. 然后紧接着创建从表(员工表)
CREATE TABLE emp3(
e_id INT PRIMARY KEY,
e_name VARCHAR(15),
dept_id INT ,
CONSTRAINT fk_emp3_dept_id FOREIGN KEY(dept_id) REFERENCES dept3(d_id) ON UPDATE CASCADE ON DELETE SET NULL
);
  • 这里我们就是以表级约束的方式为从表中的dept_id字段和主表中的d_id字段建立了外键约束,并且设置了外键约束等级为: on update cascade on delete set null, 也就是对于update操作,我们的外键约束等级是cascade(也就是同步修改),对于delete操作我们的外键约束等级是set null(也就是主表删除之后,从表对应字段设置为null)
  • 这里我们可以发现,我们的外键约束等级是在设置外键约束时给定,通过 : on update 约束等级 on delete 约束等级 的方式
注意:对于外键约束,我们最好采用ON UPDATE CASCADE ON DELETE RESTRIT的方式(也就是修改主表,那么从表跟着修改,但是不允许删除主表中的被外键约束的字段当我们从表中又对应数据时)

那么我们如何删除外键约束?

我们删除外键约束之后要手动的删除外键约束对应的普通索引

我们先删除外键约束

ALTER TABLE emp1
DROP FOREIGN KEY fk_emp1_dept_id;
  • 这里就已经将我们的emp1表中的名为fk_emp_dept_id的外键约束删除了

而在删除了外键约束之后我们要删除这个外键约束对应的普通索引

ALTER TABLE emp1
DROP INDEX fk_emp1_dept_id;
  • 注意: 外键约束对应的普通索引的索引名和外键约束名相同

外键约束(foreign key) [MySQL][数据库]相关推荐

  1. mysql数据库教程 外键_myMySQL数据库外键约束怎么写 MySQL数据库使用教程

    mysql外键约束的写法:[[CONSTRAINT ] FOREIGN KEY 字段名 REFERENCES 主键列1].外键约束是表的一个特殊字段,经常与主键约束一起使用. 在 CREATE TAB ...

  2. SQL约束(主键约束 primary key、外键约束 foreign key、唯一约束unique 、CHECK约束)

    注意: A.表中有数据不能创建约束 B.视图下设置后,要点击保存(只有保存后在才看的到) c   别忘了,点刷新,才会出来呀! 1.主键约束 primary key 主键是每行的唯一标识符,仅仅通过它 ...

  3. MySQL外键约束-foreign key

    一.什么是外键 外键也称之为外键约束 :  关键字  foreign key 外键:外面的键,一张表的一个字段(非主键)指向另外一个表的主键, 那么该字段就称之为外键. 外键所在的表称之为子表(附表) ...

  4. mysql外键约束cascade_mysql外键约束foreign key ON DELETE CASCADE ON UPDATE CASCADE

    正 文: 一,什么是foreign key,及其完整性 个人觉得,foreign key就是表与表之间的某种约定的关系,由于这种关系的存在,我们能够让表与表之间的数据,更加的完整,关连性更强.关于完整 ...

  5. Mysql外键约束foreign key

    2019独角兽企业重金招聘Python工程师标准>>> 前提:使用外键功能,存储引擎需为InnoDb类型: 一.建表时同时创建外键 1.情景,班级表 和 学生表,一对多的关系. 2. ...

  6. 主键约束(PRIMARY KEY) [MySQL][数据库]

    主键约束(PRIMARY KEY) 主键约束的特点: 主键约束相当于唯一性约束+ 非空约束,主键约束不允许重复,也不允许出现空值 一个表最多只能有一个主键约束,建立主键约束可以在列级别创建,也可以再表 ...

  7. mysql外键名_MySQL外键(foreign key)使用及说明详解

    外键也称之为外键约束: foreign key 外键: 外面的键, 一张表的一个字段(非主键)指向另外一个表的主键, 那么该字段就称之为外键. 外键所在的表称之为子表(附表); 外键所指向的主键所在的 ...

  8. mysql 说明外码_MySQL外键(foreign key)使用及说明详解

    外键也称之为外键约束: foreign key 外键: 外面的键, 一张表的一个字段(非主键)指向另外一个表的主键, 那么该字段就称之为外键. 外键所在的表称之为子表(附表); 外键所指向的主键所在的 ...

  9. MySQL中的外键(foreign key)

    引言 在MySQL中,我们都对主键比较了解,知道主键的主要作用是唯一区分表中的各个行:但是,对于外键(foreign key) 比较陌生.那么什么是外键呢?外键的作用是什么呢? 一.外键.外键作用及其 ...

最新文章

  1. ms sql 主键自动生成32位guid
  2. html+li标签+高度,有时在使用Jquery插入LI元素时,JavaScript不会调整UL元素的高度
  3. 计算机网络-信道的极限容量
  4. 成功解决np.array(zip(x1, x2)).reshape(len(x1), 2) ValueError: cannot reshape array of size 1 int
  5. java数组 序列化_程序猿的日常——Java基础之clone、序列化、字符串、数组
  6. wxWidgets:wxAny类用法
  7. CSS干货直击:腾讯无边界访问控制体系建设
  8. java.lang.NoClassDefFoundError
  9. Java中父类的静态变量和静态方法的继承问题
  10. 2018-1-27:内存的划分
  11. mysql 安全问题_浅谈MySQL数据库的Web安全问题
  12. [Nescafé41]异化多肽(多项式求逆元)
  13. 改变风格(css)的四种方法
  14. JavaScript常用注释规范
  15. 奔图打印linux驱动下载,奔图P3060DW打印机驱动下载_奔图P3060DW打印机驱动官方下载-太平洋下载中心...
  16. 运行vs2017安装程序自动退出的解决
  17. Swift网络请求框架Moya的使用
  18. 记录下生活:ETC卡充值(上海)
  19. 什么是软件测试及其分类?
  20. oracle drop tablespace 恢复杀手锏

热门文章

  1. English notes for Disease
  2. 计算机考研和新闻学考研科目,新闻学考研:各校新闻学考研科目是什么?
  3. 查找作者发行的图书总数,按图书总数进行前十名的排名
  4. 了解SPI总线CAN控制器 MCP2515配置 一文即可
  5. 项目选题报告(待就业六人组)
  6. C#—驱动打印机条码打印
  7. Ubuntu:让桌面显示回收站
  8. 从青铜到王者,进阶数据可视化2.0的五个Python库
  9. Java简单的输入 Scanner
  10. springboot yml 配置redis_springboot快速集成redis,事务配置