MySQL之外键

一:MySQL外键

  • 引入(比喻)
1.1.定义一张员工表
id	name	age 	dep_name	dep_desc
1	jason	18		外交部		搞外交
2	kevin	28		教学部		教书育人
3	tony	38		教学部		教书育人
4	oscar	48		安保部		保家卫国
5	jackson	58		财务部		发工资
2.上述表不合理之处
1.表内部数据混乱(可忽略)
2.反复的录入重复数据(可忽略)
3.修改数据太过繁琐  浪费磁盘空间(可忽略)
4.极大地影响了操作数据的效率
3.将上述表拆分成两张表
id	name	age 
1	jason	18
2	kevin	28
3	tony	38
4	oscar	48
5	jackson	58

id	dep_name	dep_desc
1	外交部		搞外交
2	教学部		教书育人
3	安保部		保家卫国
4	财务部		发工资
  • 拆分完之后解决了上述四个缺陷
4.外键
用来记录表与表之间的关系
dep_id
id name age dep_id
1 jason 18 1
2 jevin 28 2
3 tony 38 2
4 oscar 48 3
5 jackson 58 4

二:如何查找表关系

1.查找表的关系
1.多对一
2.多对多
3.一对一
4.没有关系
2.多对一:(示例图)

image

3.查找表关系:换位思考
书籍表与出版社表
1.先站在书籍表
问:一本书能够对应多个出版社
答:不可以
2.再站在出版社表
问:一个出版社能否对应多本书
答:可以
结论:一个可以一个不可以 表关系为"多对一"
那么外键字段建在"多"的一方
  • 针对具有表关系的SQL建议先写普通字段 最后再考虑外键字段

三:多对一(外键)实战

1.创建表(书籍关联表)
create table book(
	id int primary key auto_increment,
    title varchar(32),
    price int,
    pub_id int,
    foreign key(pub_id) references publish(id)
);
foreign key(关联表) references publish(被关联表)
作用:
book的pud_id字段 跟publish的id字段是(外键)关联的
注意:
(pud_id里面的字段永远只能写publish里面出现过的值)
创建表(出版社被关联表)
create table publish(
	id int primary key auto_increment,
    name varchar(32)
);
  • 必须先创建被关联表
    image
2.添加写入数据
  • 在写入数据的时候也需要先写入被关联表
被关联数据(写入数据):
insert into publish(name) values('北方出版社'),('东方出版社');


关联数据(写入数据):
insert into book(title,price,pub_id) values('linux入门',666666,1),('python入门',88888888,1);

image

四:外键约束

1.外键约束问题
1.在创建表的时候需要先创建被关联表(没有外键的表)
详解:
    因为没有被关联表的话 无法识别到被关联表的时候就会导致报错

2.在写入数据的时候也需要先写入被关联表(没有外键的表)
详解:
    在存储数据的时候,没有被关联表的外键字段,关联表也无法关联,会导致报错
    
3.被关联表里面的数据无法直接删除和修改关联字段的操作
详解:
    如果被关联表被删除了,那么关联表的外键字段就不知道指向谁了,会导致数据混乱 
2.如何删除或修改被关联表
如果要修改或者删除被关联表的字段的话,那么关联表的字段也要同样被修改或删除才合理
该方法提供处理 被关联字段的删除与修改
关键字(级联更新 级联删除):
        on update cascade 
        on delete cascade

五:级联更新 级联删除

1.创建表必须先创建(被关联表)
关联表

create table emp(
	id int primary key auto_increment,
    name varchar(32),
    age int,
    dep_id int,
    foreign key(dep_id) references dep(id) 
    on update cascade 
    on delete cascade
);

注意:
on updata cascade与on delete cascade不要加逗号因同属于一条命令

被关联表

create table dep(
	id int primary key auto_increment,
    name varchar(32)
);
2.存储数据(先写入被关联表)
关联表
insert into emp(name,age,dep_id) values('jason',18,1),('kevin',19,2),('jack',29,3),('tom',30,2);

被关联表
insert into dep(name) values('外交部'),('保安部'),('财务部');

image

六:多对多

1.以书籍表与作者表为例
1.先站在书籍表的基础之上
    问:一本书能否对应多个作者
    答:可以
2.在站在作者表的基础之上
    问:一个作者能否对应多本书
    答:可以

结论:两个都可以那么表关系就是"多对多"
外键字段建在第三张关系表中
image

book_id		: 永远只能出现书籍表的id
author_id	: 永远只能出现作者表的id
2.错误的创建方式(创建多对多)
create table book1(
	id int primary key auto_increment,
    title varchar(32),
    author_id int,
    foreign key(author_id) references author1(id) 
    on update cascade 
    on delete cascade
);

create table author1(
	id int primary key auto_increment,
    name varchar(32),
    book_id int,
    foreign key(book_id) references book1(id) 
    on update cascade 
    on delete cascade
);

image

3.原因:
以上为错误的方式:
    两张表都是关联表,无法进行关联,所以报错
4.解决多对多无法创建问题(第三方关联表)
被关联表(书籍表)
create table book1(
	id int primary key auto_increment,
    title varchar(32)
);

被关联表(作者表)
create table author1(
	id int primary key auto_increment,
    name varchar(32)
);

第三方关联表(相当于中转站)
create table book2author(
	id int primary key auto_increment,
    author_id int,
    foreign key(author_id) references author1(id) 
    on update cascade 
    on delete cascade,
    book_id int,
    foreign key(book_id) references book1(id)
    on update cascade 
    on delete cascade
);
5.存储数据(写入表内数据)
书籍表
insert into book1(title) values('python入门'),('java入门'),('linux入门');

作者表
insert into author1(name) values('ojbk'),(jason);

第三方关联表
insert into book2author(book_id,author_id) values(1,1),(2,1);
insert into book2author(book_id,author_id) calues(2,2),(2,3)

image

  • 总结:多对多的关系,需要建立在第三张表上进行

七:表关系之一对一和没有关系

1.以用户表与用户详情表为例
1.先站在用户表的基础之上
    问:一个用户能否对应多个用户详情
    答:不可以
2.在站在用户详情表基础之上
    问:一个用户详情能否对应多个用户
    答:不可以

image

结论:换位思考之后两边都不可以 那么表关系有两种

1.没有关系(用膝盖都能判断出来)
2.一对一关系
2.外键字段建在哪里?
理论上建在任何一方都可以但是推荐建在查询频率较高的表中

3.创建一对一表关系(案例)

用户表(关联表)

create table user(
	id int primary key auto_increment,
    name varchar(32),
    detail_id int unique,
    foreign key(detail_id) references user_detail(id)
    on update cascade
    on delete cascade
);

注意:
detail_id int unique		: 一对一关系,不能出现重复外键
注意:
先创建被关联表
用户详细表(被关联表)
create table user_detail(
	id int primary key auto_increment,
    addr varchar(32),
    phone bigint
);
4.存储数据(先写入被关联表)
存入(用户详细表)
insert into user_detail(addr,phone) values('安徽',123),('江苏',110);
存入(用户表)
insert into user(name,detail_id) values('objk',1);

image

5.总结
一对一关系,只需要添加上unique,不能重复外键,因为是一对一关系。
posted @ 2022-01-26 22:19  AlexEvans  阅读(301)  评论(0编辑  收藏  举报