外键
说到表与表之间的关系就不得不说到一个关键词:外键
MySQ中的外键是什么,和表与表之间有什么关联?
外键(foreign key)又叫外连接, 在数据库中发挥着重要的作用 尤其是对于表和表之间的关系尤为重要
通过示例说明:
员工信息表有三个字段:工号 姓名 部门 如何把他们相互联系起来呢??
公司有3个部门,但是有1个亿的员工,那意味着部门这个字段需要重复存储,部门名字越长,越浪费
解决方法:
我们完全可以定义一个部门表,然后让员工信息表关联该表,如何关联,即foreign key
#表类型必须是innodb存储引擎,且被关联的字段,即references指定的另外一个表的字段,必须保证唯一create table department(id int primary key,name varchar(20) not null)engine=innodb;#dpt_id外键,关联父表(department主键id),同步更新,同步删除create table employee(id int primary key,name varchar(20) not null,dpt_id int,constraint fk_name foreign key(dpt_id)references department(id)on delete cascadeon update cascade )engine=innodb;#先往父表department中插入记录insert into department values(1,'欧德博爱技术有限事业部'),(2,'艾利克斯人力资源部'),(3,'销售部');#再往子表employee中插入记录insert into employee values(1,'egon',1),(2,'alex1',2),(3,'alex2',2),(4,'alex3',2),(5,'李坦克',3),(6,'刘飞机',3),(7,'张火箭',3),(8,'林子弹',3),(9,'加特林',3);#删父表department,子表employee中对应的记录跟着删mysql> delete from department where id=3;mysql> select * from employee;+----+-------+--------+| id | name | dpt_id |+----+-------+--------+| 1 | egon | 1 || 2 | alex1 | 2 || 3 | alex2 | 2 || 4 | alex3 | 2 |+----+-------+--------+#更新父表department,子表employee中对应的记录跟着改mysql> update department set id=22222 where id=2;mysql> select * from employee;+----+-------+--------+| id | name | dpt_id |+----+-------+--------+| 1 | egon | 1 || 3 | alex2 | 22222 || 4 | alex3 | 22222 || 5 | alex1 | 22222 |+----+-------+--------+
通过上面的示例 我们可以发现:其实表和表之间是存在一定的关系的 那么 我们怎么找出表和表之间的关系呢??
分析步骤:#1、先站在左表的角度去找是否左表的多条记录可以对应右表的一条记录,如果是,则证明左表的一个字段foreign key 右表一个字段(通常是id)#2、再站在右表的角度去找是否右表的多条记录可以对应左表的一条记录,如果是,则证明右表的一个字段foreign key 左表一个字段(通常是id)#3、总结:#多对一:如果只有步骤1成立,则是左表多对一右表如果只有步骤2成立,则是右表多对一左表#多对多如果步骤1和2同时成立,则证明这两张表时一个双向的多对一,即多对多,需要定义一个这两张表的关系表来专门存放二者的关系#一对一:如果1和2都不成立,而是左表的一条记录唯一对应右表的一条记录,反之亦然。这种情况很简单,就是在左表foreign key右表的基础上,将左表的外键字段设置成unique即可
通过以上的方法可以找到表和表之间的 关系,既然找到了这种关系或者叫关联 我们就可以用表把他们之间的关联表现出来(即表与表之间的关系):
表和表之间的关系
一对多或者叫多对一
三张表:出版社,作者信息,书 实现三者的联系一对多(或多对一):一个出版社可以出版多本书 关联方式:foreign key=====================多对一=====================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 cascadeon update cascade);insert into press(name) values('北京工业地雷出版社'),('人民音乐不好听出版社'),('知识产权没有用出版社');insert into book(name,press_id) values('九阳神功',1),('九阴真经',2),('九阴白骨爪',2),('独孤九剑',3),('降龙十巴掌',2),('葵花宝典',3)
多对多
三张表:出版社,作者信息,书 实现相互关联多对多:一个作者可以写多本书,一本书也可以有多个作者,双向的一对多,即多对多 关联方式:foreign key+一张新的表=====================多对多=====================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 cascadeon update cascade,constraint fk_book foreign key(book_id) references book(id)on delete cascadeon update cascade,primary key(author_id,book_id));#插入四个作者,id依次排开insert into author(name) values('egon'),('alex'),('yuanhao'),('wpq');#每个作者与自己的代表作如下1 egon: 1 九阳神功 2 九阴真经 3 九阴白骨爪 4 独孤九剑 5 降龙十巴掌 6 葵花宝典2 alex: 1 九阳神功 6 葵花宝典3 yuanhao: 4 独孤九剑 5 降龙十巴掌 6 葵花宝典4 wpq: 1 九阳神功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#一定是student来foreign key表customer,这样就保证了:#1 学生一定是一个客户,#2 客户不一定是学生,但有可能成为一个学生create table customer(id int primary key auto_increment,name varchar(20) not null);create table student(id int primary key auto_increment,name varchar(20) not null,class_name varchar(20) not null default 'python自动化',level int default 1,customer_id int unique, #该字段一定要是唯一的foreign key(customer_id) references customer(id) #外键的字段一定要保证uniqueon delete cascadeon update cascade);#增加客户insert into customer(name) values('李飞机'),('王大炮'),('守榴弹'),('吴坦克'),('赢火箭'),('战地雷');#增加学生insert into student(name,customer_id) values('李飞机',1),('王大炮',2);
相关练习题:
账号信息表,用户组,主机表,主机组
#用户表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与usergroupcreate 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与businesscreate 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与hostcreate 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);