数据库--外键--用法/缺点

原文网址:

简介

        本文介绍数据库的外键的用法以及其缺点。

        实际上,项目中很少用到外键,因为缺点很明显,《阿里巴巴开发手册》也明确写明不要使用物理外键。

创建外键的条件

  1. 父表和子表引擎一致,否则报错;
  2. 保证表的存储引擎为InnoDB,否则虽然不报错但是无约束(只有index);
    1. 实际上,如果两个表都是MyISAM 引擎的,错误根本不会发生,但也不会产生外键。
  3. 两个字段数据类型一致,数据显示长度可以不同,另外需注意有符号无符号,必须一致;
  4. 两个字段都添加了独立索引,如果子表外键字段无索引,那么在创建外键的时候会自动先添加索引;如果父表字段无索引,将报错;
  5. 字段是否允许为空,在更新或删除时候对外键字段操作有关;如外键创建时候 on delete set null on udpate cascade。但是子表外键字段不允许为空, 矛盾,创建不成功。
  6. 字段的字符集和校对集(外键类型为字符的时候);
  7. 外键名字不能重复,是针对数据库而不是表;
  8. 子表外键字段 - 数据 为父表引用字段子集;
  9. 字段可能为混合键值中一个,没有自己独立索引。外键字段必须有自己独立索引。

外键的作用

外键默认的作用有两点:一个对父表,一个对子表(外键字段所在的表)。

作用1:对子表约束

        子表数据在进行写操作(增和改)的时候,如果对应的外键字段在父表找不到对应的匹配,那么操作会失败。插入的时候外键字段值要么为null,要么为父表中字段。

INSERT INTO my_foreign1 VALUES(null,'嘉嘉',12,40)

插入的40为外键字段数据,在父表中对应的被引用字段无此数据值,则会报如下错误: 

数据库--外键--用法/缺点

作用2:对父表约束

        父表数据进行写操作(删和改:都必须涉及到字段本身),如果对应的字段在子表中已经被数据所引用,那么就不允许操作。

INSERT INTO my_foreign1 VALUES(null,'皇甫',18,2)
INSERT INTO my_foreign1 VALUES(null,'嘉嘉',12,4)

        在父表上进行UPDATE/DELETE以更新或删除在子表中有一条或多条对应匹配行的候选键时,父表的行为取决于:在定义子表的外键时指定的ON UPDATE/ON DELETE子句。

外键约束模式

        外键约束有三种约束模式:都是针对父表; 对应MySQL有四种约束:RESTRICT,NO ACTION , CASCADE , SET NULL。

关键字

含义

示例

RESTRICT

如果子表中有匹配的记录,则不允许对父表对应候选键进行UPDATE/DELETE操作。

(这是默认设置,也是最安全的设置)

ALTER TABLE my_foreign1 add CONSTRAINT fk_id
FOREIGN KEY (p_id) REFERENCES  p_user_2(id) 
ON DELETE NO ACTION ON UPDATE NO ACTION;

-- 或者
ON DELETE RESTRICT ON UPDATE RESTRICT;

NO ACTION

与RESTRICT相同。

CASCADE

在父表上UPDATE/DELETE时,同步UPDATE/DELETE掉子表的匹配记录 ALTER TABLE my_foreign1 add CONSTRAINT fk_id
FOREIGN KEY (p_id) REFERENCES  p_user_2(id) 
ON DELETE CASCADE ON UPDATE CASCADE;

SET NULL

在父表上UPDATE/DELETE时,将子表上匹配记录的列设为NULL。

外键置为NULL的前提是对应字段允许为空,否则外键创建不成功。

ALTER TABLE my_foreign1 add CONSTRAINT fk_id
FOREIGN KEY (p_id) REFERENCES  p_user_2(id) 
ON DELETE SET NULL ON UPDATE SET NULL;

SET DEFAULT

父表有变更时,子表将外键列设置成一个默认的值。但Innodb不能识别。

通常一个合理的做法(约束模式)是:删除的时候子表置空,更新的时候子表级联:ON DELETE SET NULL ON UPDATE CASCADE;

不要用外键索引

阿里手册:

数据库--外键--用法/缺点

物理外键的优点

  1. 保证数据的完整性和一致性
  2. 级联操作方便
  3. 将数据完整性判断托付给了数据库完成,减少了程序的代码量
  4. 如果通过物理外键解决我的bug比逻辑外键更简单

物理外键的缺点

  1. 性能问题:  比如每次像A表中插入数据都会去B表查询是否有对应数据,如果不止一个外键呢?如果批量插入或更新呢?
  2. 并发问题:  在使用外键的情况下,每次修改数据都需要去另外一个表检查数据,需要获取额外的锁。若是在高并发大流量事务场景,使用外键更容易造成死锁。
  3. 扩展性问题:  比如表结构重构,mysql迁移到oracle,分表分库,是不是会顿时感到头痛

其他网址

mysql 外键(foreign key)的详解和实例_数据库_差不多先生-CSDN博客
MySQL中外键的定义、作用、添加和删除_数据库_不当初-CSDN博客

【数据库外键】为什么不推荐使用物理外键?_corleone_4ever的博客-CSDN博客
MySQL - 外键使用详解_小小默:进无止境-CSDN博客
QL中外键的作用与使用场景_爱喝咖啡的程序猫的博客-CSDN博客

上一篇:【组队学习】动手学数据分析 Task1


下一篇:Day 17:Python 对象的相等性比较