前奏:
日常会遇到一个表里存在许多的数据,其实是存在一定的弊端的:
1、组织结构不清晰
2、浪费硬盘空间
3、扩展性极差
上述的弊端产生原因类似于把代码全部写在一个py文件里,此时我们最好将其拆成多个表格,也就是解耦合。
外键的使用:
多对一的情况: 1、在创建表时,先建被关联的表dep,再建立关联表emp create table dep( id int primary key auto_increment, dep_name char(10), dep_comment char(60) ); create table emp( id int primary key auto_increment, name char(16), gender enum('male','female') not null default 'male', dep_id int, foreign key(dep_id) references dep(id) ); 2、在插入记录时,必须先插入被关联的表dep后,才能插入关联表emp insert into dep(dep_name,dep_comment) values ('教学部','辅导学生学习'), ('外交部','形象大使'), ('技术部','解决问题'); insert into emp(name,gender,dep_id) values ('aaa','male',1), ('bbb','male',2), ('ccc','male',1), ('ddd','male',1), ('eee','female',3); # 当想修改emp里的dep_id或dep里面的id时返现都无法成功 此处的dep是被关联的表 # 当想删除dep表的教学部的时候,也无法删除 # 方式:先删除教学部对应的所有的员工,再删除教学部,也就是先把关联的emp表的教学部所对应的数据全删除。 # 此时产生一个问题:受限于外键约束,导致操作数据变得非常复杂,能否有一张简单的方式,让我不需要考虑在操作目标表的时候还去考虑关联表的情况,比如我删除部门,那么这个部门对应的员工就应该跟着立即清空---增加语句: on delete cascade #此时需要把之前的数据清空,重新操作 create table dep( id int primary key auto_increment, dep_name char(10), dep_comment char(60) ); create table emp( id int primary key auto_increment, name char(16), gender enum('male','female') not null default 'male', dep_id int, foreign key(dep_id) references dep(id) on update cascade on delete cascade ); insert into dep(dep_name,dep_comment) values ('教学部','辅导学生学习'), ('外交部','形象大使'), ('技术部','解决问题'); insert into emp(name,gender,dep_id) values ('aaa','male',1), ('bbb','male',2), ('ccc','male',1), ('ddd','male',1), ('eee','female',3);
查看表中内容,做个参考
delete from emp where dep_id=1;
此时发现,删除关联表中的数据,被关联表中数据却不会有什么改变。 原因是:只能通过对被关联的表进行操作,关联的表中数据会自动同步 删除部门后,对应的部门里面的员工表数据会对应删除,更新也是一样 delete from dep where id =3;
多对多
类似于 图书与作者的关系:一本书可以由多个作者一起创作,一个作者可以出版多本书
先来想如何创建表?图书表需要有一个外键关联作者,作者也需要有一个外键字段关联图书。 create table author( id int primary key auto_increment, name char(10) ); create table book( id int primary key auto_increment, bname char(10), price int ); insert into author(name) values ('aaa'), ('bbb'), ('ccc); insert into book(bname,price) values ('金瓶妹',200), ('葵花宝',800), ('九阴真经',500), ('九阳神功',100); 到这步会发现,让谁成为被关联对象都不合适 此时需要在创建第三方的一个表来处理这种情况 create table author2book( 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 key(book_id) references book(id) on update cascade on delete cascade ); insert into author2book(author_id,book_id) values (1,3), (1,4), (2,2), (2,4), (3,1), (3,2), (3,3), (3,4);
查看原始结果;
delete from book where id=3;
对被关联的book表操作删除了一行数据,关联的表author2book数据会发生改变,另外一个author表没有改变。
一对一:
例如:一个人进入了一家培训机构,发现里面的条件还不错,就选择留下来进修。报名之前是客户,报名之后是学生。
create table customer( id int primary key auto_increment, name char(20) not null, qq char(10) not null, phone char(16) not null ); create table student( id int primary key auto_increment, class_name char(20) not null, customer_id int unique, #该字段一定要是唯一的 foreign key(customer_id) references customer(id) #外键的字段一定要保证unique on delete cascade on update cascade );
修改表:
小点:msql对大小写不敏感! 语法: 1、修改表名 alter table 表名 rename 新表名 2、增加字段 alter table 表名 add 字段名 数据类型[约束条件] alter table 表名 add 字段名 数据类型[约束条件] first #把增加的字段放到第一位 alter table 表名 add 字段名 数据类型[约束条件] after #把增加的字段放到最后一位 3、删除字段 alter table 表名 drop 字段名 delete from 表名 where 条件 4、修改字段 alter table 表名 change 旧字段名 新字段名 旧数据类型[约束条件] alter table 表名 change 旧字段名 新字段名 新数据类型[约束条件] alter table 表名 modify 字段名 数据类型[约束条件] #modify 只能修改字段类型和完整约束,不能更改字段名
复制表:
理解:查询语句执行的结果也是一张表,将其当成虚拟表 复制表结构+记录 不会复制:主键、外键和索引 create table new_server select * from server; 只复制表结构; select * from server where 1=2; #条件为假,查不到任何记录 create table new_server select * from server where 1=2; #只 存在表的结构。表里的具体数据为空 create table ttt like server; #复制索引和主外键,存在表的结构,但是没有具体的表里的数据。
补充点:表之间的数据转移: 复制旧表的数据到新表(两个表的结果一样) insert into new_form select * from old_form; 复制旧表的数据到新表(两个表的结构不一样) insert into new_form(字段1,字段2....) select 字段1, 字段2,...from old_form;