• 数据库--多表关系


    多表关系

    一对多

    表1-->表2 一对多
    表2-->表1 多对一

    例如:一个部门有多个老师,而一个老师只有一个部门。此时部门表是主表,老师表是从表

    create table dept(
    	id int,
    	name char(10),
    	primary key(id)	# 主键
    	);
    create table teacher(
    	id int,
    	name char(10),
        dept_id int,
    	primary key(id),	# 主键
    	foreign key(dept_id) references dept(id)  # 外键
    	);
    

    多对多

    表1-->表2 多对多

    表2-->表1 多对多

    例如:一个老师可以教多门课程,一门课程也可以有多个老师教,这么这就是多对多的关系,没有主从之分,所以外键也不便添加,因为外键的类型最好是int,这样便于修改和添加。

    处理方式:

    • 建立一个中间表3,专门用来储存表1和表2间的关系,至少具备两个字段,分别指向表1和表2的主键,这两个字段都是外键约束。这张表属于表1和表2的从表。
    create table course(
    	id int primary key auto_increment,
    	name char(10)
    	);
    create table teacher(
    	id int primary key auto_increment,
    	name char(10)
    	);
    create table c_t_rel(
    	cou_id int,
    	tea_id int,
    	foreign key(cou_id) references course(id),
    	foreign key(tea_id) references teacher(id)
    	);
    
    • 这种方式确实做到了多对多,但是如何保证没有重复添加相同的关系呢?

    方法一:给两个字段分别设置为联合唯一+非空

    # 修改表
    alter table c_t_rel modify cou_id int not null unique;
    alter table c_t_rel modify tea_id int not null unique;
    # 创建表
    create table c_t_rel2(
    	cou_id int not null,
    	tea_id int not null,
    	not null key(cou_id, tea_id),
        unique key(cou_id, tea_id)
    	);
    

    方法二:将中间的关系表3中的两个id,作为联合主键(多字段主键)

    # 推荐
    create table c_t_rel(
    	cou_id int,
    	tea_id int,
    	primary key(cou_id, tea_id),
    	foreign key(cou_id) references course(id),
    	foreign key(tea_id) references teacher(id)
        );
    

    总结

    1. 创建两个主表,如课程表和老师表
    2. 创建一个关系表,包含两个字段
    3. 两个字段设置为联合主键,并且分别设置外键,对应主表的主键

    查询方式

    如果我们想要查找,python有哪些老师教了,步骤为

    1. 通过课程名python在课程表中找到id
    2. 通过id去关系表中找到老师的id
    3. 通过老师的id拿到老师的名字
    select id from course where name='python';
    # 为什么这里有引号也能找
    select tea_id from c_t_rel where cou_id=1;
    select * from teacher where id=1 or id=2;
    

    子查询方式

    • 把语句A的结果作为另一条语句B的条件
    # 如果语句A的结果有两个值,那么id就要用in,一个值就用=
    							# 两个值                                    # 一个值
    select * from teacher where id in (select tea_id from c_t_rel where cou_id=(select id from course where name='python'));
    

    一对一

    这种情况比较少见,因为一般的一对一,都不需要进行分表操作。

    但是当一个表中数据量太大的时候,为了提高效率,将一些不是很常用的数据拆分到另一个表中。称之为垂直分表。

    例如:人员表,和信息详情表

    # 人员表
    create table person(
    	id int primary key auto_increment,
    	name char(10)
    	);
    
    # 详情表
    create table person_info(
    	id int primary key,
    	height float,
    	weight float,
        foreign key(id) references person(id)
    	);
    # 在这个例子中,必须先插入主表也就是person,拿到一个id,再添加详情表的数据,有点类似于多对一关系
    

    补充:垂直分表,水平分表

    垂直分表:把一个表的部分字段分到另一个表中。

    水平分表:两个表的字段完全一致,只是把数据拆分开来提高效率

  • 相关阅读:
    面试题:能谈谈Date、Datetime、Time、Timestamp、year的区别吗?
    面试题:对NotNull字段插入Null值 有啥现象?
    聊聊什么是慢查、如何监控?如何排查?
    谈谈MySQL的基数统计
    .vimrc
    HISKrrr的板子库
    CSP 模拟35
    晚测1
    CSP 模拟34
    nim板子题异或正确性YY
  • 原文地址:https://www.cnblogs.com/lucky75/p/11196914.html
Copyright © 2020-2023  润新知