MySQL外键约束要求与参照操作

文章目录

  • 约束
    • FOREIGN KEY 外键约束
    • 如何编辑数据表的默认存储引擎
    • 外键约束的创建
    • 外键约束的参照操作
    • 表级约束和列级约束

约束

1.约束是为了保证数据的完整性和一致性
2.约束分为表级约束和列级约束
(1)如果约束针对一个字段进行约束,那么就称为列级约束
(2)如果针对两个以上字段的约束,那么就称为表级约束
3.约束类型包括
(1)NULL --非空约束
(2)PRIMARY KEY --主键约束
(3)UNIQUE KEY --唯一约束
(4)DEFAULT --默认约束
(5)FOREIGN KEY --外键约束

现在来说外键约束,其他约束在上篇文章的mysql基础用法中

FOREIGN KEY 外键约束

两个目的
1.保证数据的一致性,完整性
2.实现一对一,一对多的关系
这也就是将很多数据库称之为“关系型数据库的关系”的根本原因
在mysql中,如果要创建外键约束,肯性需要有一些要求
1.要求父表和子表必须使用相同的存储引擎,而且禁止使用临时表。
(1)所谓的子表指的是具有外键列的表,称之为“子表”
(2)而子表所参照的表,我们称之为父表
2.存储表的数据引擎只能为innoDB。
3.外键列和参照列必须具有相同的数据类型,如果是数字的话则要求数字的长度以及是否有符号位这些属性必须相同,而字符长度可以不同。
(1)曾加过FOREIGN KEY关键词的那一列,我们称之为外键列
(2)而外键列所参照的那一列称之为参照列
4.外键列和参照列必须创建索引。参照列没有索引的话MySQL将自动创建索引,外键列不存在索引,mysql不予理睬。

如何编辑数据表的默认存储引擎

MySQL配置文件
default-storage-engine=INNIDB
如果忘记了mysql安装路径,则用一下命令查找

show variables like "%char%";

MySQL外键约束要求与参照操作_第1张图片
MySQL外键约束要求与参照操作_第2张图片
更改后重新启动mysql的服务

外键约束的创建

那么相同的引擎,且存储引擎只能为INNODB这个条件就已经满足了
那么
外键列和参照列必须具有相同的数据类型,如果是数字的话则要求数字的长度以及是否有符号位这些属性必须相同,而字符长度可以不同
我们来创建两张表,让他们存在相同的数据类型
第一张:省份表(provinces)

CREATE TABLE provinces(
    -> id SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    -> pname VARCHAR(20) NOT NULL
    -> );

在这里插入图片描述
那么这张表是否使用了我们创建的默认引擎呢?
我们可以通过命令查看

SHOW CREATE TABLE provinces;

MySQL外键约束要求与参照操作_第3张图片
引擎没错

在provinces中只要id和省份名两个字段,下边来创建另外的一张数据表
首先来两个字段,一个id,一个用户名,除了存储这两个字段以外,加入我还想存储用户所在的省份,以前我们需要加一个省份的字段,添加为字符类型,现在有了关系型数据库,我们只需要存储省份的编号即可,所以我们来存储pid,用其来存储省份的编号,这个pid以后就是我们的外键,参照主键包provinces,也就是我们的父表中的id的字段,现在我们先来试一下数据类型不一致能否实现我们的外键约束。

CREATE TABLE users(
    -> id SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    -> username VARCHAR(20) NOT NULL,
    -> pid BIGINT,
    -> FOREIGN KEY (pid) REFERENCES provinces (id)
    -> );

MySQL外键约束要求与参照操作_第4张图片
告诉我们不能添加外键约束,为啥尼,因为数据类型不一致
修改一下

CREATE TABLE users(
    -> id SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    -> username VARCHAR(20) NOT NULL,
    -> pid SMALLINT,
    -> FOREIGN KEY (pid) REFERENCES provinces (id)
    -> );

MySQL外键约束要求与参照操作_第5张图片
依然不可以,因为我们父表中设置的是有符号位,这里没有设置,默认是无符号位,是不是这里不可以尼?

CREATE TABLE users(
    -> id SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    -> username VARCHAR(20) NOT NULL,
    -> pid SMALLINT UNSIGNED,
    -> FOREIGN KEY (pid) REFERENCES provinces (id)
    -> );

MySQL外键约束要求与参照操作_第6张图片
嗯嗯,蒙对了,看来是这样的。

这里大家就要必须清楚
1、父表子表分别指的是谁
2、users,有外键的这张表称之为子表,我们多参照的表,provinces则称之为父表
3、引擎都为INNODB
4、外键列和参照列具有相同或类似的数据类型(在数字的情况下,必须相同,字符情况可以不同)
5、外键列和参照列必须创建索引,因为我们参照列中id已经添加了主键,主键在创建的同事会自动添加索引,所以说参照列已经有了索引
我们来证明一下是否存在索引

SHOW INDEXES FROM provinces\G;

MySQL外键约束要求与参照操作_第7张图片
可见我们的id字段上已经存在索引,所以说我们当前的参照列上已经有了索引,那外键列上我们并没有为pid指定主键,那有没有创建索引呢?

SHOW INDEXES FROM users\G;

MySQL外键约束要求与参照操作_第8张图片
我们可以发现在users表中一共存在两个外键,一个是主键索引,id字段上我们创建主键已经添加了索引,除此之外在pid上已自动的创建索引,我们查看一下users表

MySQL外键约束要求与参照操作_第9张图片
我们可以清晰的看到,除了我们家的primary key (id)以外,key pid是系统给我们自带的,实际上就已经给我们加了索引,也可以看见曾经写过的constrint约束 ,foreign key典型的外键约束

外键约束的参照操作

创建外键的时候我们还可以写上针对于外键约束的参照的一些操作
在参照操作中一共存在四个选项,分别是cascade,set null, restrict,no action,是指在进行了外键越是的创建以后在更新表的时候子表是否也进行了响应的操作,我们来看一看

1、CASCADE:从父表中删除或更新且自动删除或更新子表中匹配的行
2、SET NULL:从父表中删除或更新行,并设置子表中的外键列为null。如果使用该选项,必须保证子表列没有设置NOT NULL
3、RESTRICT:拒绝对父表的删除或更新操作
4、NOT ACTION:标准的SQL关键字,在MySQL中与RESTRICT相同

下边来举例说明:
刚才的users表没有任何参照操作,我们来新建一张,操作添加cascade

CREATE TABLE users(
    -> id SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    -> username VARCHAR(20) NOT NULL,
    -> pid SMALLINT UNSIGNED,
    -> FOREIGN KEY (pid) REFERENCES provinces (id) ON DELETE CASCADE
    -> );

MySQL外键约束要求与参照操作_第10张图片
MySQL外键约束要求与参照操作_第11张图片
CASCADE是指从父表中删除或更新且自动删除或更新子表中匹配的行,我们来做个试验,既然后更新相应的行,也就代表我们必须在数据表准存在着相应的记录才可以,所以说我们要分别在两张表中插入记录,另外如果我们要在两张表中插入记录的话,我们一定要注意,必须现在父表中cha插入记录,因为子表操作的是父表中的信息,如果父表中不存在信息,那么子表就无法参照,所以我们必须现在provinces中插入记录,刚才的省份表只有两个字段,一个id一个pname,id是主键自动编号,我们就只插入省份名即可,

INSERT provinces(pname) VALUES("A");
INSERT provinces(pname) VALUES("B");
INSERT provinces(pname) VALUES("C");

MySQL外键约束要求与参照操作_第12张图片

SELECT *FROM provinces;

MySQL外键约束要求与参照操作_第13张图片
嗯嗯,插进去了,没问题

那我们向子表插入数据
我们的子表users1,三个字段,分别是id,和 username 和pid,id是主键,所以我们只需要插入username和pid即可,也就是用户名和对应的用户所在省份

INSERT users1  (username,pid) VALUES ("TOM",3)
INSERT users1  (username,pid) VALUES ("JOHN",1)
INSERT users1  (username,pid) VALUES ("ROSE",3)

也就是TOM是C省的
JOHN是A省的
ROSE也是C省的
就这个个意思

MySQL外键约束要求与参照操作_第14张图片

这个时候我妈们把provinces表中的C省这条记录删除掉,

DELETE FROM provinces WHERE id = 3;

在这里插入图片描述
删除成功并告诉我们1条记录被影响

查一下provinces,数据删除掉了
MySQL外键约束要求与参照操作_第15张图片
在查一下users1表
MySQL外键约束要求与参照操作_第16张图片
这就验证了我们外键操作CASCADE,当参照表中记录删除或更改子表自动删除或更新匹配行,没有毛病吧,如果,不想删,子表变成null,那就用SET NULL即可,注意子表列不可设置为not null

表级约束和列级约束

约束按照不同的标准来划分,不同的结果,我们之所以把它划分为not null,主键约束,唯一约束,是根据他的功能实现的,而如果说按照操作数目的多少,我们能把它划分成表级和列级约束,

对于一个数据列所创建的约束,我们称之为列级
对于多个数据列所创建的约束,我们称之为表级
列级约束在使用的时候既可以既可以在列定义的时候声明,也可以在列定义以后声明
而表级的约束只能在列定义以后声明
not null约束和default约束就不存在表级约束,只有列级约束,对于其他的三种,主键primary key ,唯一约束unique key,外键约束foreign key他们都可以存在表级和列级约束

你可能感兴趣的