数据库的主键和外键详解

MySQL数据库的主键和外键详解

主键

主键的定义

主键:表中常常有一个列或多列的组合,其值能惟一地标识表中的每一行。这样的一列或多列称为表的主键,经过它可强制表的实体完整性。当建立或更改表时可经过定义 PRIMARY KEY 约束来建立主键。一个表只能有一个 PRIMARY KEY 约束,并且 PRIMARY KEY 约束中的列不能接受空值。因为 PRIMARY KEY 约束确保惟一数据,因此常常用来定义标识列。mysql

做用:算法

1)保证明体的完整性;sql

2)加快数据库的操做速度数据库

3)在表中添加新记录时,DBMS会自动检查新记录的主键值,不容许该值与其余记录的主键值重复。编程

4)DBMS自动按主键值的顺序显示表中的记录。若是没有定义主键,则按输入记录的顺序显示表中的记录。编程语言

联合主键性能

关系数据库实际上还容许经过多个字段惟一标识记录,即两个或更多的字段都设置为主键,这种主键被称为联合主键。code

对于联合主键,容许一列有重复,只要不是全部主键列都重复便可。blog

主键的特性

主键的必要性图片

在有些数据库中,虽然主键不是必需的,但最好为每一个表都设置一个主键,不论是单主键仍是复合主键。它存在表明着表结构的完整性,表的记录必须得有惟一区分的字段,主键主要是用于其余表的外键关联,以及本记录的修改与删除。

主键的无心义性

因为主键的做用十分重要,如何选取主键会对业务开发产生重要影响。若是咱们以学生的身份证号做为主键,彷佛能惟必定位记录。然而,身份证号也是一种业务场景,若是身份证号升位了,或者须要变动,做为主键,不得不修改的时候,就会对业务产生严重影响。

选取主键的一个基本原则是:不使用任何业务相关的字段做为主键。

所以,身份证号、手机号、邮箱地址这些看上去能够惟一的字段,均不可用做主键。

主键的选择

  • 自增整数类型:数据库会在插入数据时自动为每一条记录分配一个自增整数,这样咱们就彻底不用担忧主键重复,也不用本身预先生成主键;
  • 全局惟一GUID类型:使用一种全局惟一的字符串做为主键,相似8f55d96b-8acc-4636-8cb8-76bf8abc2f57。GUID算法经过网卡MAC地址、时间戳和随机数保证任意计算机在任意时间生成的字符串都是不一样的,大部分编程语言都内置了GUID算法,能够本身预算出主键。

对于大部分应用来讲,一般自增类型的主键就能知足需求

定义的自增性整数类型的主键通常使用是BIGINT NOT NULL AUTO_INCREMENT类型。

若是使用INT自增类型,那么当一张表的记录数超过2147483647(约21亿)时,会达到上限而出错。使用BIGINT自增类型则能够最多约922亿亿条记录。

外键

外键的定义

若是公共关键字在一个关系中是主关键字,那么这个公共关键字被称为另外一个关系的外键。因而可知,外键表示了两个关系之间的相关联系。以另外一个关系的外键做主关键字的表被称为主表,具备此外键的表被称为主表的从表。外键又称做外关键字。

举例:

student表:
在这里插入图片描述
class表:
在这里插入图片描述
因为一个班级能够有多个学生,在关系模型中,这两个表的关系能够称为“一对多”,即一个class的记录能够对应多个student表的记录。

为了表达这种一对多的关系,咱们须要在student表中加入一列class_id,让它的值与class表的某条记录相对应。

这样,咱们就能够根据class_id这个列直接定位出一个student表的记录应该对应到class的哪条记录。

student表中,经过class_id的字段,能够把数据与另外一张表关联起来,这种列称为外键

外键并非经过列名实现的,而是经过定义外键约束实现的:

//定义外键约束
ALTER TABLE student
ADD CONSTRAINT fk_class_id  //外键约束的名称fk_class_id能够任意
FOREIGN KEY (class_id)     //指定了class_id做为外键
REFERENCES class (id);    //指定了这个外键将关联到class表的id列(即class表的主键)

class_id为学生表的外键。(此时student表中的class_id与class表中的id表示的含义相同)

此时外键表是student表,主键表是class表。

要删除一个外键约束,也是经过ALTER TABLE实现的:

ALTER TABLE student
DROP FOREIGN KEY fk_class_id;

因为外键约束会下降数据库的性能,大部分互联网应用程序为了追求速度,并不设置外键约束,而是仅靠应用程序自身来保证逻辑的正确性。这种状况下,class_id仅仅是一个普通的列,只是它起到了外键的做用而已。

选取设置 MySQL 外键的字段

定义一个外键时,须要遵照下列规则:

  • 父表必须已经存在于数据库中,或者是当前正在建立的表。若是是后一种状况,则父表与子表是同一个表,这样的表称为自参照表,这种结构称为自参照完整性。
  • 必须为父表定义主键。
  • 主键不能包含空值,但容许在外键中出现空值。也就是说,只要外键的每一个非空值出如今指定的主键中,这个外键的内容就是正确的。
  • 在父表的表名后面指定列名或列名的组合。这个列或列的组合必须是父表的主键或候选键。
  • 外键中列的数目必须和父表的主键中列的数目相同。
  • 外键中列的数据类型必须和父表主键中对应列的数据类型相同。

外键的做用

保持数据一致性,完整性。主要目的是控制存储在外键表中的数据。 使两张表造成关联,外键只能引用外表中的列的值或使用空值

外键约束

MySQL外键约束(FOREIGN KEY)用来在两个表的数据之间创建连接,它能够是一列或者多列。一个表能够有一个或多个外键。

外键是表的一个字段,不是本表的主键,但对应另外一个表的主键。定义外键后,不容许删除另外一个表中具备关联关系的行。

  • 主表(父表)

    对于两个具备关联关系的表而言,相关联字段中主键所在的表就是主表。

    被引用的表叫主表(父表)。

  • 从表(子表)

    对于两个具备关联关系的表而言,相关联字段中外键所在的表就是从表。

    定义了外键的表叫从表(子表)。

外键约束的做用:

阻止执行

  • 从表插入新行,其外键值不是主表的主键值便阻止插入;
  • 从表修改外键值,新值不是主表的主键值便阻止修改;
  • 主表删除行,其主键值在从表里存在便阻止删除(要想删除,必须先删除从表的相关行);
  • 主表修改主键值,旧值在从表里存在便阻止修改(要想修改,必须先删除从表的相关行)。

级联执行

  • 主表删除行,连带从表的相关行一块儿删除;
  • 主表修改主键值,连带从表相关行的外键值一块儿修改。两种方法提供给用户选择。不管选取哪一种方法,从表里都不会有多余行。从另外一个角度理解,用拒绝同一事物在从表中的标志与主表不一致来实现与主表中的标志一致。

两种实现方法,经过下面方式选择:

  • 界面:设级联更新、级联删除两个选择方框,选取则级联执行、不选取则阻止执行;
  • 命令:设E)kSCM)E、RESTRICT两个可选项,CASCADE为级联执行、RESTRICT为阻止执行。

CASCADE:级联删除

在外键表的最后,加上on delete cascade 就是级联删除

再删除主表数据时和主表关联的子表数据也会删除

CREATE TABLE `student` (
  `id` bigint(64) NOT NULL AUTO_INCREMENT,
  `class_id` bigint(64) DEFAULT NULL,
  `name` varchar(32) COLLATE utf8_bin DEFAULT NULL,
  `age` int(32) DEFAULT NULL,
  `sex` varchar(32) COLLATE utf8_bin DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_class_id` (`class_id`),
  CONSTRAINT `fk_class_id` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`)  
    on delete cascade,
)

所谓的级联删除,就是删除主键表的同时,外键表同时删除。

以上面的例子将就是,假如班级表中的某个班级被删除了,那么在学生表中要想查询这个被删除的班级号所对应的班级信息就会报错,由于已经不存在这个班级了,因此,删除班级表(主键表)时必须删除其余与之关联的表,这里就说明了外键的做用,保持数据的一致性、完整性。固然反过来说,你删除学生表中的记录,并不影响班级表中的数据,你查询班级号也能正确查询。因此删除外键表中的数据并不影响主键表。

RESTRICT:约束/限制、NO ACTION(非活动,默认)

当取值为No Action或者Restrict时,则当在主键表中删除对应记录时,首先检查该记录是否有对应外键,若是有则不容许删除。(即外键表约束主键表)

SET NULL:级联置空

在在外键表的最后,加上on delete set null就是级联置空

再删除主表数据时,会把和主表关联的外键设置成NULL

CREATE TABLE `student` (
  `id` bigint(64) NOT NULL AUTO_INCREMENT,
  `class_id` bigint(64) DEFAULT NULL,
  `name` varchar(32) COLLATE utf8_bin DEFAULT NULL,
  `age` int(32) DEFAULT NULL,
  `sex` varchar(32) COLLATE utf8_bin DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_class_id` (`class_id`),
  CONSTRAINT `fk_class_id` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`)  
   on  delete  set null,
)

当取值为Set Null时,则当在主键表中删除对应记录时,首先检查该记录是否有对应外键,若是有则设置子表中该外键值为null,(同样是外键表约束主键表,不过这就要求该外键容许取null)。

NO ACTION和RESTRICT的区别:只有在及个别的状况下会致使区别,前者是在其余约束的动做以后执行,后者具备最高的优先权执行。

注意

删除表时,应该先删子表,后删父表,除非使用casecade constraints 解除关联。

先删除父表时会报错:有一个被foreign keys关联的 key的字段在子表中

<e>查询:drop table class

错误代码: 3730
Cannot drop table 'class' referenced by a foreign key constraint 'fk_class_id' on table 'student'.

若是必定要先删除父表

使用casecade constraints解除关联就能够删掉父表

drop table parent cascade constranints;

在这里插入图片描述

若有须要的朋友能够关注个人公众号并回复:数据库电子书 ,便可获取如下免费PDF资料
在这里插入图片描述

相关文章
相关标签/搜索