'''
定义一张员工表,表中有很多字段
id name gender dep_name dep_desc
1 mike male 外交部 漂泊游荡
2 jack male 教学部 教书
3 mali female 教学部 教书
4 egon male 教学部 教书
5 tank female 技术部 果实能力者
# 1:该表的组织结构不是很清晰(可忽视)
2:浪费硬盘空间(可忽视) >>>数据量大的话,部门和部门描述的数据都是重复的
3:数据的扩展性极差(无法忽视) >>>如果要修改一个部门名称,那么全部数据都要进行修改
如何优化?上述问题就类似于你将所有的代码都写在了一个py文件中
将员工表拆分成员工表和部门表
id name gender dep_id
1 mike male 1
2 jack male 2
3 mali female 2
4 egon male 2
5 tank female 2
id dep_name dep_desc
1 外交部 漂泊游荡
2 教学部 教书
3 技术部 果实能力者
外键
外键就是用来帮助我们建立表与表之间关系
foreign key
表关系
表与表之间最多只有四种关系
一对多关系
在MySQL的关系中没有多对一
一对多/多对一,都叫一对多
多对多关系
一对一关系
没有关系
'''
一对多关系
'''
判断表与表之间关系的时候,前期不熟悉的情况下,一定要按照建议进行换位思考,分别站在两张表的角度考虑
员工表与部门表为例
先站在员工表
思考一个员工能否对应多个部门(一条员工数据能否对应多条部门数据)
不能(不能直接得出结论,一定要两张表都考虑完全)
再站在部门表
思考一个部门能否对应多个员工(一个部门数据能否对应多条员工数据)
能
得出结论
员工表与部门表是单向的一对多,所以表关系就是一对多
foreign key
1:一对多表关系,外键字段建在多的一方(员工表)
2:在创建表的时候,一定要先建被关联表(部门表)
3:在录入数据的时候,也必须先录入被关联表(部门表)
sql语句建立表关系
create table dep(
id int primary key auto_increment,
dep_name char(16),
dep_desc char(32)
);
create table emp(
id int primary key auto_increment,
name char(16),
gender enum('male','female','others') default 'male',
dep_id int,
foreign key(dep_id) references dep(id) # emp表的dep_id字段与dep表的id字段有关联
);
insert into dep(dep_name,dep_desc) values('教学部','教书育人'),('外交部','多人外交'),('技术部','技术能力者');
insert into emp(name,dep_id) values('jason',2),('egon',1),('tank',1),('kevin',3);
# 修改dep表里面的id字段
update dep set id=200 where id=2; 不行
# 删除dep表里面的数据
delete from dep; 不行
# 1:先删除教学部对应的员工数据,之后再删除部门
操作太过于繁琐
# 2:真正做到数据之间有关系
更新就同步更新
删除就同步删除
级联更新,级联删除
create table dep(
id int primary key auto_increment,
dep_name char(16),
dep_desc char(32)
);
create table emp(
id int primary key auto_increment,
name char(16),
gender enum('male','female','others') default 'male',
dep_id int,
foreign key(dep_id) references dep(id)
on update cascade # 同步更新
on delete cascade # 同步删除
);
insert into dep(dep_name,dep_desc) values('教学部','教书育人'),('外交部','多人外交'),('技术部','技术能力者');
insert into emp(name,dep_id) values('jason',2),('egon',1),('tank',1),('kevin',3);
update dep set id=200 where id=2;
delete from dep where id=1;
'''
多对多关系
'''
图书表和作者表
create table book(
id int primary key auto_increment,
title varchar(32),
price int,
author_id int,
foreign key(author_id) references author(id)
on update cascade
on delete cascade
);
create table author(
id int primary key auto_increment,
name varchar(32),
age int,
book_id int,
foreign key(book_id) references book(id)
on update cascade
on delete cascade
);
按照上述的方式创建,一个都别想成功!其实我们只是想记录书籍和作者的关系
针对多对多字段表关系,不能在两张原有的表中创建外键
需要你单独再开设一张表,专门用来存储两张表数据之间的关系
create table book(
id int primary key auto_increment,
title varchar(32),
price int
);
create table author(
id int primary key auto_increment,
name varchar(32),
age int
);
create table book_to_author(
id int primary key auto_increment,
author_id int,
book_id int,
foreign key(author_id) references author(id)
on update cascade
on delete cascade,
foreign kry(book_id) references book(id)
on update cascade
on delete cascade
);
'''
一对一关系
'''
id name age addr phone hobby email...
如果一个表的字段特别多,每次查询又不是所有的字段都能用得到
将表一分为二
用户表
用户表
id name age
用户详情表
id addr phone hobby email...
站在用户表
一个用户能否对应多个用户详情
站在详情表
一个详情能否属于多个用户
结论:单向的一对多都不成立,那么这个时候两者之间的表关系要么就是一对一,或者没有关系
一对一关系,外键字段建在任意一方都可以,但是推荐建在查询频率比较高的表中
create table authordetail(
id int primary key auto_increment,
phone int,
addr varchar(64)
);
create table author(
id int primary key auto_increment,
name varchar(32),
age int,
authordetail_id int unique, # 这里必须要唯一
foreign key(authordetail_id) references authordetail(id)
on update cascade
on delete cascade
);
补充:表与表之间如果有关系的话,可以有两种建立联系的方式
1:就是通过外键强制性的建立关系
2:就是自己通过sql语句逻辑层面上建立关系
delete from emp where id=1;
delete from dep where id=1;
创建外键会消耗一定的资源,并且增加了表与表之间的耦合度
在实际项目中,如果表特别多,其实可以不做任何外键处理,直接通过sql语句来建立逻辑层面上的关系
到底用不用外键取决于实际项目需求
'''
修改表
'''
mysql对大小写是不敏感的
1 修改表名
alter table 表名 rename 新表名;
2 增加字段
alter table 表名 add 字段名 字段类型(宽度) 约束条件; # 添加在最后面
alter table 表名 add 字段名 字段类型(宽度) 约束条件 first; # 添加在最前面
alter table 表名 add 字段名 字段类型(宽度) 约束条件 after 字段名; # 指定跟在某个字段后面
3 删除字段
alter table 表名 drop 字段名;
4 修改字段
alter table 表名 modify 字段名 字段类型(宽度) 约束条件; # modify一般都是用来修改字段的字段类型和约束条件等,不能修改字段名
alter table 表民 change 旧字段名 新字段名 字段类型(宽度) 约束条件;
'''
复制表
'''
sql语句的查询结果其实也是一张虚拟表
create table 新表名 select * from 旧表名; # 不能复制主键/外键...
create table 新表名 select * from 旧表名 where id>1;
'''