MySQL 外键 表与表的关系 多对一,多对多,一对一,表的修改 与 复制

前奏:

  日常会遇到一个表里存在许多的数据,其实是存在一定的弊端的:

  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;

  

  

 

 

 

 

                                                                                 

 

posted on 2019-05-14 17:17  michael-chang  阅读(1668)  评论(0编辑  收藏  举报

导航