• foreign key外键和表关系


    六. foreign key

    强调: 表类型必须是innodb存储引擎,且被关联的字段,即references指定的另外一个表的字段,必须保证唯一

    1. 定义一张员工表的三个缺点

    employee /ɪmˈplɔɪiː/ 雇员 员工 雇员

    id emp_name emp_gender dep_name dep_desc
    1 jason male 外交部 漂泊游荡
    2 egon female 教学部 教书育人
    3 tank male 教学部 教书育人
    4 kevin male 教学部 教书育人
    5 oscar female 技术部 技术能力有限部门
    Copy# 定义一张员工表 表中有很多字段. 我们从中可以看出以上表的三个缺点
    """
    <1> 该表的组织结构不是很清晰(可忽视)
    <2> 浪费硬盘空间(可忽视)
    <3> 数据的扩展性极差(无法忽视的)
    """
    

    2. 优化: 将员工表拆分. 拆分成员工表和部门表

    员工表: emp

    employee /ɪmˈplɔɪiː/ 雇员 员工 雇员

    id emp_name emp_gender
    1 jason male
    2 egon female
    3 tank male
    4 kevin male
    5 oscar female

    部门表: dep

    department /dɪˈpɑːtmənt/ 部门

    id dep_name dep_desc
    1 外交部 漂泊游荡
    2 教学部 教书育人
    3 技术部 技术能力有限部门

    3. 外键foreign key介绍

    Copy"""
    外键就是用 来帮助我们建立表与表之间关系的
    """
    

    4. 四种表关系介绍

    Copy# 表与表之间最多只有四种关系:
    """
    # 注意!!: 得出表之间的关系结论一定要进行双向的对比. 
    <1> 一对多关系
    <2> 多对多关系
    <3> 一对一关系
    <4> 没有关系(了解)
    """
    

    5. 使用foreign key建立一对多关系

    员工表: emp

    employee /ɪmˈplɔɪiː/ 雇员 员工 雇员

    id emp_name emp_gender dep_id
    1 jason male 1
    2 egon female 2
    3 tank male 2
    4 kevin male 2
    5 oscar female 3

    部门表: dep

    department /dɪˈpɑːtmənt/ 部门

    id dep_name dep_desc
    1 外交部 漂泊游荡
    2 教学部 教书育人
    3 技术部 技术能力有限部门
    Copy# 先确定表与表之间的关系
    """
    先站在员工表考虑: 员工表里面的一个员工能否对应部门表里面的多个部门. --> 不能!!
        再站在部门表考虑: 部门表里面的一个部门能否对应员工表里面的多个员工. --> 可以!!
        结论: 员工表与部门表只是单向的一对多,那么员工表和部门表就是"一对多"的表关系.
    """
    
    """
    注意1: 一对多表关系   外键字段建在多的一方.  --> emp
    注意2: 在创建表的时候 一定要先建立被关联表.  -->  dep
    注意3: 在插入数据的时候 必须先往被关联表插值. --> dep
    
    # foreign key使用完整语法
        foreign key(关联表字段) references 表名(被关联表字段) on update cascade on delete cascade
    """
    
    # =================== 使用foreign key建立关联 ===================
    create table dep(
        id int primary key auto_increment,
        dep_name varchar(16),
        dep_desc varchar(32)
    );
    insert into dep(dep_name, dep_desc) values('外交部', '漂泊游荡'), ('教学部', '教书育人'), ('技术部', '技术能力有限部门');
    
    create table emp(
        id int primary key auto_increment,
        emp_name varchar(16),
        emp_gender enum('male', 'female'),
        dep_id int,
        foreign key(dep_id) references dep(id)
    );
    insert into emp(emp_name, emp_gender, dep_id) values('jason', 'male', 1), ('egon', 'female', 2), ('tank', 'male', 2), ('kevin', 'male', 2), ('oscar', 'female', 3);
    desc dep;
    desc emp;
    select * from dep;
    select * from emp;
    
    # 使用外键关联以后2表被外键关联的字段所对应的记录都不能进行更新. 员工表的: dep_id  部门部门表的: id
    update emp set dep_id=200 where dep_id=2;
    update dep set id=200 where id=2;
    
    # 使用外键的部门表不能进行记录的删除.
    delete from dep where id=2;
    delete from emp where id=2; # 员工表可以
    
    
    
    
    """删除的2种方式"""
    # 第一种: 先删除关联表(emp), 再删除被关联表(dep). 无论是争对记录的删除delete, 还是表的删除规则都是不变.
    delete from emp where id=1;
    delete from dep where id=1;
    
    # 第二种: 使用级联更新, 级联删除
    '''
    级联更新(同步更新) on update cascade
    级联删除(同步删除) on delete cascade
    '''
    drop table emp;
    drop table dep;
    create table dep(
        id int primary key auto_increment,
        dep_name varchar(16),
        dep_desc varchar(32)
    );
    insert into dep(dep_name, dep_desc) values('外交部', '漂泊游荡'), ('教学部', '教书育人'), ('技术部', '技术能力有限部门');
    
    create table emp(
        id int primary key auto_increment,
        emp_name varchar(16),
        emp_gender enum('male', 'female'),
        dep_id int,
        foreign key(dep_id) references dep(id)
        on update cascade  # 级联更新
        on delete cascade  # 级联删除
    );
    insert into emp(emp_name, emp_gender, dep_id) values('jason', 'male', 1), ('egon', 'female', 2), ('tank', 'male', 2), ('kevin', 'male', 2), ('oscar', 'female', 3);
    desc dep;
    desc emp;
    select * from dep;
    select * from emp;
    
    # 更新部门表的id. 员工表中得dep_id也会发生同样的改变
    update dep set id=200 where id=2;
    select * from dep;
    select * from emp;
    
    # 删除某一个部门表. 与部门表所关联的所有员工都会被清除.
    delete from dep where id=1;
    select * from dep;
    select * from emp;
    

    6. 使用foreign key建立多对多关系

    注意: 争对多对多的表关系, 不能在两张原有的表中创建外键进行关联. 需要建立中间表来关联2表之间的关系.

    图书表: book

    id title price author_id
    1 python入门到放弃 21000 1,2
    2 葵花宝典 6666 1,2
    3 前端 9 1
    4 水浒传 123 2

    作者表: author

    id name age book_id
    1 jsaon 18 1,2
    2 egon 78 3,4
    Copy# 先确定表与表之间的关系
    """
    先站在书籍表考虑: 一本书可不可以有多个作者. --> 可以!!
        再站在作者表考虑: 一个作者可不可以写多本书. --> 可以!!
        结论: 书籍表和作者表是双向的多对多, 那么表关系就是"多对多"关系.
    """
    
    create table book(
        id int primary key auto_increment,
        title varchar(32),
        price int,
        author_id int,
        foreign key(autor_id) references author(id)
        on update cascade  # 级联更新
        on delete cascade  # 级联删除
    );
    
    create table author(
        id int primary key auto_increment,
        title varchar(32),
        age int,
        book_id int,
        foreign key(book_id) references book(id)
        on update cascade  # 级联更新
        on delete cascade  # 级联删除
    );
    
    """按照上述的方式创建 一个都别想成功!!"""
    

    中间表: book2author

    注意1: 如果一本书有多个作者必须重新开启一行.

    注意2: 建立了中间表以后中间表与上面2表是多对一的关系. 新建的中间表是多的一方, 上面2表是一的一方. 所以因该先创建上面2表, 再创建需要建立外键关联中间表

    • 一个book2author中的id可以对应多个作者. --> 不成立
    • 一个作者可以对应多个book2author中的多个id --> 成立
    id book_id author_id
    1 1 1
    2 1 2
    3 2 1
    4 2 2
    5 3 2
    6 4 1
    Copycreate table book(
        id int primary key auto_increment,
        title varchar(16) not null,
        price int not null
    );
    insert into book(title, price) values('python入门到放弃', 21000), ('葵花宝典', 6666), ('前端', 9), ('水浒传', 123);
    
    create table author(
        id int primary key auto_increment,
        name varchar(16) not null,
        age int not null
    );
    insert into author(name, age) values('jsaon', 18), ('egon', 78);
    
    
    # 针对多对多字段表关系 不能在两张原有的表中创建外键 需要你单独再开设一张 专门用来存储两张表数据之间的关系
    create table book2author(
        id int primary key auto_increment,
        book_id int not null,
        author_id int not null,
        foreign key(book_id) references book(id)
        on update cascade   # 级联更新
        on delete cascade,  # 级联删除
        foreign key(author_id) references author(id)
        on update cascade  # 级联更新
        on delete cascade  # 级联删除
    );
    insert into  book2author(book_id, author_id) values(1, 1), (1, 2), (2, 1), (2, 2), (2, 2), (3, 2), (4, 1);
    
    select * from book;
    select * from author;
    select * from book2author;
    

    7. 使用foreign key建立一对一关系

    注意: 对于一对一关系表authordetail_id使用过就不能使用, 应该在外键的基础之上使用unique.

    detail /ˈdiːteɪl/ 细节 详情 零件

    id name age authordetail_id
    1 jsaon 18 1
    2 egon 73 2

    作者详情表: authordetail

    id postcode address
    1 335000 鹰潭市
    2 200050 上海市
    Copy# 先确定表与表之间的关系
    """
    站在作者的角度:
        一个作者可以对象多个用户详情. --> 不成立
    站在详情的角度:
        一个用户详情可以对应多个作者. --> 不成立
    结论: 一对一    
    """
    # 强调!!!: 外键字段建在任意一方都可以 但是推荐你建在查询频率比较高的表中(author)
    
    create table authordetail(
        id int primary key auto_increment,
        postcode int not null,
        address varchar(64) not null
    );
    insert into authordetail(postcode, address) values(335000, '鹰潭市'), (200050, '上海市');
    
    create table author(
        id int primary key auto_increment,
        name varchar(16) not null,
        age int not null,
        authordetail_id int not null unique,  # 注意: 对于一对一关系表authordetail_id使用过就不能使用, 应该在外键的基础之上使用unique.
        foreign key(authordetail_id) references authordetail(id) 
        on update cascade
        on delete cascade  
    );
    insert into author(name, age, authordetail_id) values('jsaon', 18, 1), ('egon', 73, 2);
    
    select * from author;
    select * from authordetail;
    

    8. 总结

    Copy# 表关系的建立需要用到foreign key
    """
    一对多:  外键字段建立在多的一方
    多对多:  开设中间表存储
    一对一:  外键字段建立在任意一方都可以, 但是推荐建立在查询频率比较高的一方
    """
    
    # 判断表之间关系的方式
    """
    从多个角度切入. 如果是2表之间的关系那么只有在2表都换位思考了以后, 才能进行判断表与表之间的关系.
    """
    
    # 使用
    foreign key(关联表字段) references 被关联表表名(被关联字段) 
    on update cascade 级联更新(同步更新)
    on delete cascade 级联删除(同步删除)
    
  • 相关阅读:
    Ionic Js十:加载动作
    Ionic Js九:列表操作
    Ionic Js八:头部和底部
    Ionic Js七:手势事件
    库文件
    驱动知识
    自启动总结
    学习笔记
    写脚本切换用户
    未找到arm-linux-gcc解决办法
  • 原文地址:https://www.cnblogs.com/jkeykey/p/14457387.html
Copyright © 2020-2023  润新知