外键

外键: 用来建立两张表之间的关系

语法: foreign key (当前表中建立关系的外键字段) references 被关联表名(id)

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

公司有3个部门,但是有很多员工,说明部门这个字段需要重复存储,部门名字越长,越浪费

解决方法: 定义一个部门表,让员工信息表关联该表,使用foreign key 关联

#建立被关联表(部门表)
create table dep(
	id int primart key auto_increment,
    dep_name varchar(16) not null,
    dep_desc varchar(50)
);

#建立关联表(员工表)  dep_id外键,同步更新(删除) 
create table emp(
	id int primary key auto_increment,
    name varchar(16) not null,
    age int,
    gender enum('male', 'female') default 'male',
    dep_id int not null,
    foreign key(dep_id) references dep(id)
    on delete cascade
    on update cascade
);

# 插入数据:
	-必须先插入被关联表的数据,再插入关联表的数据

#dep
insert into dep(dep_name, dep_desc) values
('外交部', '出台'),('销售部','销售'),('才艺部','唱跳rap');

+----+-----------+-----------+
| id | dep_name  | dep_desc  |
+----+-----------+-----------+
|  1 | 外交部    | 出台      |
|  2 | 销售部    | 销售      |
|  3 | 才艺部    | 唱跳rap   |
+----+-----------+-----------+

#emp
insert into emp(name, age, gender, dep_id) values
('yyh', 23, 'male', 1),
('xxt', 24, 'male', 2),
('ldh', 24, 'male', 3),
('hys', 26, 'male', 1);

+----+------+------+--------+--------+
| id | name | age  | gender | dep_id |
+----+------+------+--------+--------+
|  1 | yyh  |   23 | male   |      1 |
|  2 | xxt  |   24 | male   |      2 |
|  3 | ldh  |   24 | male   |      3 |
|  4 | hys  |   26 | male   |      1 |
+----+------+------+--------+--------+

#报错
insert into emp(name, age, gender, dep_id) values
('ysk', 12, 'male', 5);

# 级联更新,级联删除
on update cascade
on delete cascade

#更新 删除记录
update dep set id=4 where id=1;
+----+-----------+-----------+
| id | dep_name  | dep_desc  |
+----+-----------+-----------+
|  2 | 销售部    | 销售      |
|  3 | 才艺部    | 唱跳rap   |
|  4 | 外交部    | 出台      |
+----+-----------+-----------+

+----+------+------+--------+--------+
| id | name | age  | gender | dep_id |
+----+------+------+--------+--------+
|  1 | yyh  |   23 | male   |      4 |
|  2 | xxt  |   24 | male   |      2 |
|  3 | ldh  |   24 | male   |      3 |
|  4 | hys  |   26 | male   |      4 |
+----+------+------+--------+--------+
delete from dep where id=2;
+----+-----------+-----------+
| id | dep_name  | dep_desc  |
+----+-----------+-----------+
|  3 | 才艺部    | 唱跳rap   |
|  4 | 外交部    | 出台      |
+----+-----------+-----------+

+----+------+------+--------+--------+
| id | name | age  | gender | dep_id |
+----+------+------+--------+--------+
|  1 | yyh  |   23 | male   |      4 |
|  3 | ldh  |   24 | male   |      3 |
|  4 | hys  |   26 | male   |      4 |
+----+------+------+--------+--------+

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

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

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

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

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

#一对一
如果1和2都不成立,而是左(右)表的一条记录唯一对应右(左)表的一条记录,就是在左表foreign key右表的基础上,将左表的外键字段设置成unique即可

#多对多 
#关联方式 foreign key + 一张新的表
#一个作者可以写几本书,一本书也可以有几个作者
1.yyh:
	1.社交宝典
	2.达盖尔的旗帜
2.xxt:
	2.达盖尔的旗帜
	3.女朋友信耶稣

3.ldh:
	2.达盖尔的旗帜
	4.性冷淡浅谈
	
#book
create table book(
	id int primary key auto_increment,
    title varchar(20),
    price int,
    book_content varchar(50)
);
#auther
create table auther(
	id int primary key auto_increment,
    name varchar(16),
    age int
);
#book2auther
create table book2auther(
	id int primary key auto_increment,
    book_id int,
    auther_id int,
    foreign key(book_id) references book(id)
    on update cascade
    on delete cascade,
    foreign key(auther_id) references auther(id)
    on update cascade
    on delete cascade
);

#插入数据
#book
insert into book(title, price, book_content) values
('社交宝典', 199, '3分钟教你把妹'),
('达盖尔的旗帜', 299, '精彩生活图集'),
('女朋友信耶稣', 399, '了解作者的手冲生活'),
('性冷淡浅谈', 499, '没有孩子到底是为什么');
+----+--------------------+-------+--------------------------------+
| id | title              | price | book_content                   |
+----+--------------------+-------+--------------------------------+
|  1 | 社交宝典           |   199 | 3分钟教你把妹                  |
|  2 | 达盖尔的旗帜       |   299 | 精彩生活图集                   |
|  3 | 女朋友信耶稣       |   399 | 了解作者的手冲生活             |
|  4 | 性冷淡浅谈         |   499 | 没有孩子到底是为什么           |
+----+--------------------+-------+--------------------------------+


#auther
insert into auther(name, age) values
('yyh', 23),
('xxt', 24),
('ldh', 25);
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | yyh  |   23 |
|  2 | xxt  |   24 |
|  3 | ldh  |   25 |
+----+------+------+


#book2auther
insert into book2auther(auther_id, book_id) values
(1, 1),
(1, 2),
(2, 2),
(2, 3),
(3, 2),
(3, 4);

+----+---------+-----------+
| id | book_id | auther_id |
+----+---------+-----------+
|  7 |       1 |         1 |
|  8 |       2 |         1 |
|  9 |       2 |         2 |
| 10 |       3 |         2 |
| 11 |       2 |         3 |
| 12 |       4 |         3 |
+----+---------+-----------+

#报错,插入的数据,book_id, auther_id必须存在
insert into book2auther(book_id, auther_id) values(4,4);

#更新或删除
#更新
update book set price=666 where id=1;
update book set id=5 where id=1;
+----+--------------------+-------+--------------------------------+
| id | title              | price | book_content                   |
+----+--------------------+-------+--------------------------------+
|  2 | 达盖尔的旗帜       |   299 | 精彩生活图集                   |
|  3 | 女朋友信耶稣       |   399 | 了解作者的手冲生活             |
|  4 | 性冷淡浅谈         |   499 | 没有孩子到底是为什么           |
|  5 | 社交宝典           |   666 | 3分钟教你把妹                  |
+----+--------------------+-------+--------------------------------+

+----+---------+-----------+
| id | book_id | auther_id |
+----+---------+-----------+
|  1 |       5 |         1 |
|  2 |       2 |         1 |
|  3 |       2 |         2 |
|  4 |       3 |         2 |
|  5 |       2 |         3 |
|  6 |       4 |         3 |
+----+---------+-----------+

#删除
delete from book where id=5;
+----+--------------------+-------+--------------------------------+
| id | title              | price | book_content                   |
+----+--------------------+-------+--------------------------------+
|  2 | 达盖尔的旗帜       |   299 | 精彩生活图集                   |
|  3 | 女朋友信耶稣       |   399 | 了解作者的手冲生活             |
|  4 | 性冷淡浅谈         |   499 | 没有孩子到底是为什么           |
+----+--------------------+-------+--------------------------------+


#一对一,两张表的关系一一对应,将一张数据量比较大的表,拆分成两张
#关联方式:foreign key + unique
用户信息:id, name, age, gender, hobby, id_card
us表:id, name, age, detail_id(外键)
detail表:id, gender, hobby, id_card


#被关联表
create table us(
	id int primary key auto_increment,
    name varchar(16),
    age int
);


#关联表
create table detail(
	id int primary key auto_increment,
    gender  enum('male', 'female') default 'male',
    hobby  set('singing','dancing','rap','ball'),
    user_id int unique,
    foreign key(user_id) references us(id)
    on update cascade
    on delete cascade
);


#插入数据
insert into us(name, age) values
('yyh', 38),('xxt', 40);
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | yyh  |   38 |
|  2 | xxt  |   40 |
+----+------+------+

insert into detail(gender, hobby, user_id) values
('male','singing,rap', 1),('female','dancing,ball',2);
+----+--------+--------------+---------+
| id | gender | hobby        | user_id |
+----+--------+--------------+---------+
|  1 | male   | singing,rap  |       1 |
|  2 | female | dancing,ball |       2 |
+----+--------+--------------+---------+

#修改表的操作
1.修改表名
 alter table 表名 rename 新表名;

2.增加字段
 alter table 表名 add 字段名 数据类型[完整性约束条件];
 alter table 表名 add 字段名 数据类型[完整性约束条件] first; # 添加到第一列
 alter table 表名 add 字段名 数据类型[完整性约束条件] after;# 添加到某一列后
 
3.修改字段
 #修改数据类型
 alter table 表名 modify 字段名 数据类型[完整性约束条件]; 
 #修改字段名,保留字段类型
 alter table 表名 change 旧字段名 新字段名 旧数据类型[完整性约束条件];
 #修改字段名与字段类型
 alter table 表名 change 旧字段名 新字段名 新数据类型[完整性约束条件];
 
 
#复制表的操作
复制表结构+记录 (key不会复制:主键、外键和索引)
create table new_service select * from service;

只复制结构
create table new_service select * from service where 1=2; 

删除表
drop table 表名;