mysql约束条件之外键

时间:2021-05-09 00:42:45

一 foreign key

一 快速理解foreign key

员工信息表有三个字段:工号  姓名  部门

公司有3个部门,但是有1个亿的员工,那意味着部门这个字段需要重复存储,部门名字越长,越浪费

解决方法:

我们完全可以定义一个部门表

然后让员工信息表关联该表,如何关联,即foreign key

mysql约束条件之外键mysql约束条件之外键
#需求:创建员工表,需要员工信息与所属部门及职责
create table emp(
    id int primary key auto_increment,
    name char(8),
    gender enum('male','female'),
    dep_name char(8),
    dep_info char(20)
);

insert into emp(name,gender,dep_name,dep_info) values
    ('张三','male','教育部','辅导学生,教授课程'),
    ('李四','male','技术部','开发软件,技术有限部门'),
    ('王二','male','教育部','辅导学生,教授课程'),
    ('麻子','male','教育部','辅导学生,教授课程'),
    ('小月','female','人事部','招收学生,安排入学');
#############创建结果#############
+----+--------+--------+-----------+-----------------------------------+
| id | name   | gender | dep_name  | dep_info                          |
+----+--------+--------+-----------+-----------------------------------+
|  1 | 张三   | male   | 教育部    | 辅导学生,教授课程                |
|  2 | 李四   | male   | 技术部    | 开发软件,技术有限部门            |
|  3 | 王二   | male   | 教育部    | 辅导学生,教授课程                |
|  4 | 麻子   | male   | 教育部    | 辅导学生,教授课程                |
|  5 | 小月   | female | 人事部    | 招收学生,安排入学                |
+----+--------+--------+-----------+-----------------------------------+
问题分析:每添加一个员工就需要在重新写一遍所属部门和职责,这样重复的代码太多,并且表的信息不够清晰
解决思路:将部门单独做成一张表,员工信息在创建时只需要添加一个部门id字段即可对应部门以及详细信息,那么两表之间的逻辑关联由谁来联系?答案就是外键(总不能让人拿着两张表去比对吧,这样也太'人工智能'了~~~)
无外键情况
mysql约束条件之外键mysql约束条件之外键
create table dep(
    id int primary key auto_increment,
    dep_name char(8),
    dep_info char(20)
);
insert dep(dep_name,dep_info) values
    ('销售部','联系客户,促谈生意'),
    ('教育部','辅导学生,教授课程'),
    ('技术部','写bug,调bug,写bug');

create table emp(
    id int primary key auto_increment,
    name char(8),
    gender enum('male','female'),
    dep_id int,
    foreign key(dep_id) references dep(id)
);
insert emp(name,gender,dep_id) values
    ('对象1','male',2),
    ('对象2','male',2),
    ('对象3','female',1),
    ('对象4','male',3),
    ('对象5','male',2),
    ('对象6','female',1);
外键语法就是在关联表中使用foreign key(关联字段) references 被关联表名(被关联字段)
############上述操作结果############
+----+---------+--------+--------+
| id | name    | gender | dep_id |
+----+---------+--------+--------+
|  1 | 对象1   | male   |      2 |
|  2 | 对象2   | male   |      2 |
|  3 | 对象3   | female |      1 |
|  4 | 对象4   | male   |      3 |
|  5 | 对象5   | male   |      2 |
|  6 | 对象6   | female |      1 |
+----+---------+--------+--------+

+----+---------+--------+--------+
| id | name    | gender | dep_id |
+----+---------+--------+--------+
|  1 | 对象1   | male   |      2 |
|  2 | 对象2   | male   |      2 |
|  3 | 对象3   | female |      1 |
|  4 | 对象4   | male   |      3 |
|  5 | 对象5   | male   |      2 |
|  6 | 对象6   | female |      1 |
外键详解
mysql约束条件之外键mysql约束条件之外键
# foreign key会带来什么样的效果?
#1、约束1:在创建表时,先建被关联的表dep,才能建关联表emp
#2、约束2:在插入记录时,必须先插被关联的表dep,才能插关联表emp
#3、设置外键增加语句on update cascade on delete cascade与外键设置为一句话  实现同步删除同步更新
外键效果

二 如何找出两张表之间的关系 

分析步骤:
#1、先站在左表的角度去找
是否左表的多条记录可以对应右表的一条记录,如果是,则证明左表的一个字段foreign key 右表一个字段(通常是id)

#2、再站在右表的角度去找
是否右表的多条记录可以对应左表的一条记录,如果是,则证明右表的一个字段foreign key 左表一个字段(通常是id)

#3、总结:
#多对一:
如果只有步骤1成立,则是左表多对一右表
如果只有步骤2成立,则是右表多对一左表

#多对多
如果步骤1和2同时成立,则证明这两张表时一个双向的多对一,即多对多,需要定义一个这两张表的关系表来专门存放二者的关系

#一对一:
如果1和2都不成立,而是左表的一条记录唯一对应右表的一条记录,反之亦然。这种情况很简单,就是在左表foreign key右表的基础上,将左表的外键字段设置成unique即可

三 建立表之间的关系

#一对多或称为多对一
三张表:出版社,作者信息,书

一对多(或多对一):一个出版社可以出版多本书

关联方式:foreign key
mysql约束条件之外键mysql约束条件之外键
=====================多对一=====================
create table press(
id int primary key auto_increment,
name varchar(20)
);

create table book(
id int primary key auto_increment,
name varchar(20),
press_id int not null,
foreign key(press_id) references press(id)
on delete cascade
on update cascade
);


insert into press(name) values
('北京工业地雷出版社'),
('人民音乐不好听出版社'),
('知识产权没有用出版社')
;

insert into book(name,press_id) values
('九阳神功',1),
('九阴真经',2),
('九阴白骨爪',2),
('独孤九剑',3),
('降龙十巴掌',2),
('葵花宝典',3)
;
多对一

 

#多对多
三张表:出版社,作者信息,书

多对多:一个作者可以写多本书,一本书也可以有多个作者,双向的一对多,即多对多
  
关联方式:foreign key+一张新的表
mysql约束条件之外键mysql约束条件之外键
=====================多对多=====================
create table author(
id int primary key auto_increment,
name varchar(20)
);


#这张表就存放作者表与书表的关系,即查询二者的关系查这表就可以了
create table author2book(
id int not null unique auto_increment,
author_id int not null,
book_id int not null,
constraint fk_author foreign key(author_id) references author(id)
on delete cascade
on update cascade,
constraint fk_book foreign key(book_id) references book(id)
on delete cascade
on update cascade,
primary key(author_id,book_id)
);


#插入四个作者,id依次排开
insert into author(name) values('egon'),('alex'),('yuanhao'),('wpq');

#每个作者与自己的代表作如下
egon: 
九阳神功
九阴真经
九阴白骨爪
独孤九剑
降龙十巴掌
葵花宝典
alex: 
九阳神功
葵花宝典
yuanhao:
独孤九剑
降龙十巴掌
葵花宝典
wpq:
九阳神功


insert into author2book(author_id,book_id) values
(1,1),
(1,2),
(1,3),
(1,4),
(1,5),
(1,6),
(2,1),
(2,6),
(3,4),
(3,5),
(3,6),
(4,1)
;
多对多

 

#一对一
两张表:学生表和客户表

一对一:一个学生是一个客户,一个客户有可能变成一个学校,即一对一的关系

关联方式:foreign key+unique
mysql约束条件之外键mysql约束条件之外键
#一定是student来foreign key表customer,这样就保证了:
#1 学生一定是一个客户,
#2 客户不一定是学生,但有可能成为一个学生


create table customer(
id int primary key auto_increment,
name varchar(20) not null,
qq varchar(10) not null,
phone char(16) not null
);


create table student(
id int primary key auto_increment,
class_name varchar(20) not null,
customer_id int unique, #该字段一定要是唯一的
foreign key(customer_id) references customer(id) #外键的字段一定要保证unique
on delete cascade
on update cascade
);


#增加客户
insert into customer(name,qq,phone) values
('李飞机','31811231',13811341220),
('王大炮','123123123',15213146809),
('守榴弹','283818181',1867141331),
('吴坦克','283818181',1851143312),
('赢火箭','888818181',1861243314),
('战地雷','112312312',18811431230)
;


#增加学生
insert into student(class_name,customer_id) values
('脱产3班',3),
('周末19期',4),
('周末19期',5)
;
一对一
mysql约束条件之外键mysql约束条件之外键
例一:一个用户只有一个博客

    用户表:
    id  name
   egon
   alex
   wupeiqi


    博客表   
           fk+unique
    id url name_id
 xxxx   1
 yyyy   3
 zzz    2



例二:一个管理员唯一对应一个用户
    用户表:
    id user  password
 egon    xxxx
 alex    yyyy

    管理员表:
       fk+unique
    id user_id password
  1      xxxxx
  2      yyyyy
其他例子

三 练习

mysql约束条件之外键mysql约束条件之外键
#用户表
create table user(
id int not null unique auto_increment,
username varchar(20) not null,
password varchar(50) not null,
primary key(username,password)
);

insert into user(username,password) values
('root','123'),
('egon','456'),
('alex','alex3714')
;


#用户组表
create table usergroup(
id int primary key auto_increment,
groupname varchar(20) not null unique
);

insert into usergroup(groupname) values
('IT'),
('Sale'),
('Finance'),
('boss')
;


#主机表
create table host(
id int primary key auto_increment,
ip char(15) not null unique default '127.0.0.1'
);

insert into host(ip) values
('172.16.45.2'),
('172.16.31.10'),
('172.16.45.3'),
('172.16.31.11'),
('172.10.45.3'),
('172.10.45.4'),
('172.10.45.5'),
('192.168.1.20'),
('192.168.1.21'),
('192.168.1.22'),
('192.168.2.23'),
('192.168.2.223'),
('192.168.2.24'),
('192.168.3.22'),
('192.168.3.23'),
('192.168.3.24')
;


#业务线表
create table business(
id int primary key auto_increment,
business varchar(20) not null unique
);
insert into business(business) values
('轻松贷'),
('随便花'),
('大富翁'),
('穷一生')
;


#建关系:user与usergroup

create table user2usergroup(
id int not null unique auto_increment,
user_id int not null,
group_id int not null,
primary key(user_id,group_id),
foreign key(user_id) references user(id),
foreign key(group_id) references usergroup(id)
);

insert into user2usergroup(user_id,group_id) values
(1,1),
(1,2),
(1,3),
(1,4),
(2,3),
(2,4),
(3,4)
;



#建关系:host与business

create table host2business(
id int not null unique auto_increment,
host_id int not null,
business_id int not null,
primary key(host_id,business_id),
foreign key(host_id) references host(id),
foreign key(business_id) references business(id)
);

insert into host2business(host_id,business_id) values
(1,1),
(1,2),
(1,3),
(2,2),
(2,3),
(3,4)
;

#建关系:user与host

create table user2host(
id int not null unique auto_increment,
user_id int not null,
host_id int not null,
primary key(user_id,host_id),
foreign key(user_id) references user(id),
foreign key(host_id) references host(id)
);

insert into user2host(user_id,host_id) values
(1,1),
(1,2),
(1,3),
(1,4),
(1,5),
(1,6),
(1,7),
(1,8),
(1,9),
(1,10),
(1,11),
(1,12),
(1,13),
(1,14),
(1,15),
(1,16),
(2,2),
(2,3),
(2,4),
(2,5),
(3,10),
(3,11),
(3,12)
;
示例

练习2:

mysql约束条件之外键