zoukankan      html  css  js  c++  java
  • 8.20MySQL(三)外键

    一、外键前戏

    1.定义一张部门员工表

    2.把所有数据都存放于一张表的弊端

      1.表的结构不清晰

      2.浪费硬盘空间

      3.表的扩展性极差(无法忽略的缺点)

    3.上述的弊端产生原因类似于把代码全部写在一个py文件中,你应该怎么做?

      解耦合!将上述一张表拆成员工和部门两张表!

    4.分析表数据之间的关系:

      多个用户对应一个部门,一个部门对应多个用户。禁止一个用户对应多个部门这种情况是另外一张表关系

    5.如何确立表与表之间的关系

      一定要换位思考(必须两方都考虑周全之后才能得出结论)

      以员工表和部门表为例:

    先站在员工表看能否有多个员工对应一个部门
        翻译过来:
            一个部门能否有多个员工
            可以!!!(暂时只能确定员工单向多对一部门)
    再站在部门表看能否有多个部门对应一个员工
        翻译过来:
            一个员工能否属于多个部门
            不可以!!!

      结论:员工表和部门表之间仅仅是单向的多对一

      那么它们的表关系就是"一对多"

      表关系中没有多对一这一说,只有一对多

      无论是多对一还是一对多都叫"一对多"

    二、外键:foreign key

      如何让两种表有代码层面上真正的关联,就必须使用外键

    1.什么是外键?

      让表与表有硬性层面上的关系

    2.关键字:

      foreign key

    三、一对多外键建立

    1.建表

      先创建被关联表,否则会报错

    create table dep(
        id int primary key auto_increment,
        dep_name varchar(32),
        dep_desc varchar(128)
    );
    create table emp(
        id int primary key auto_increment,
        emp_name varchar(64),
        emp_gender enum('male','female','others') default 'male',
        dep_id int,
        foreign key(dep_id) references dep(id)    
    );

      再插入数据,也必须先插入被关联表的数据

    insert into dep(dep_name,dep_desc) values('外交部','搞外交'),
    ('教学部','教书育人'),
    ('技术部','技术能力有限部门');
    insert into emp(emp_name,dep_id) values('jason',1),
    ('egon',2),
    ('tank',2),
    ('kevin',3);

      外键约束:

        1.在创建表的时候,必须先创建被关联表

        2.插入数据的时候,也必须先插入被关联表的数据

    2.修改表数据

      update dep set id=200 where id = 1;  # 无法修改

      update emp set dep_id = 300 where id = 1;  # 也无法修改

      删除数据也同样不行

      外键虽然能够帮你强制建立表关系,但是也会给表之间增加数据相关的约束

    3.如何才能删除

      1.删除数据的时候,先删员工表的数据,再删部门表的数据

        delete from emp where id = 4;

        delete from dep where id = 3;

      2.级联更新:on update cascade,级联删除:on delete cascade

        更新部门后,对应员工表中的标示部门的字段同步更新

        删除部门后,对应的部门里面的员工表数据对应删除

    # 先创建被关联表
    create table dep(
        id int primary key auto_increment,
        dep_name varchar(32),
        dep_desc varchar(128)
    );
    
    create table emp(
        id int primary key auto_increment,
        emp_name varchar(64),
        emp_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(emp_name,dep_id) values('jason',1),
    ('egon',2),
    ('tank',2),
    ('kevin',3);
    
    
    update dep set id=200 where id = 3;  # 修改被关联表的数据成功
    delete from dep where id = 2;  # 删除被关联表的数据成功

    四、多对多关系的建立

    1.图书与作者表(一定要换位思考):

      先站在图书

        多本书能否有一个作者

          一个作者能否写多本书,可以!!!

      再站在作者

        多个作者能否和写一本书

          一本书能否有多个作者,可以!!!

    如果双方都是可以,那么就是多对多

    强调:foreign key 只是用来帮你建表关系的,不是某个关系特有的方法

    2.多对多关系的建立

      必须手动创建第三张表,用来专门记录两张表之间的关系

    先建两张普通的表,不需要设置外键

    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 book2author(
            id int primary key auto_increment,
            book_id int,
            foreign key(book_id) references book(id)
            on update cascade
            on delete cascade,
            author_id int,
            foreign key(author_id) references author(id)
            on update cascade
            on delete cascade
       );

    插入数据

    insert into book(title,price) values('西游记',199),('聊斋',299),('jason教你删别人的库,让别人跑路',1);
    
    insert into author(name,age) values('jason',18),('tank',38);
    
    insert into book2author(book_id,author_id) values(4,3);  # 报错,必须要在两张表的id范围里
    insert into book2author(book_id,author_id) values(1,1),(1,2),(2,1),(3,1),(3,2); 

    五、一对一表关系的建立

    1.一对一表关系

      1.一对一的场景:当你的表特别庞大的时候,你可以考虑拆分表

      2.联想老男孩的客户和学生(老男孩的客户与学生之间,报名之前都是客户,只有报了名的才能是学生)

        当你没有交学费之前,你是老男孩的客户

        当你交了学费之后,你就变成老男孩的学生

        是所有的客户都能变成学生吗?

    2.通常将关系字段,称之为:外键字段

      一对多的外键字段,建在多的一方

      多对多的外键字段,建在第三张表

      一对一的外键字段,建在任意一方都可以,但是推荐你建在查询频率较高的一方

    3.建立

    # 先创建被关联表
    create table authordetail(
            id int primary key auto_increment,
            phone int,
            addr char(255)
    
    );
    
    
    create table author(
        id int primary key auto_increment,
        name char(4),
        age int,
        authordetail_id int unique,
        foreign key(authordetail_id) references authordetail(id)
        on update cascade
        on delete cascade
    );

    六、判断表关系的最简单的语法

      图书与出版社

        一本书可不可以有多个出版社  不可以!!!

        一个出版社可不可以出版多本书  可以!!!

        一对多的关系

      图书与作者

        一本书可不可以有多个作者  可以!!!

        一个作者可不可以写多本书  可以!!!

        多对多的关系

      作者与作者详情

        一个作者可不可以有多个详情  不可以!!!

        一个作者详情可不可以有多个作者  不可以!!!

        要么两者是一对一

        要么两者之间没任何关系

    七、了解知识点

    1.修改表的完整语句

      1. 修改表名

        ALTER TABLE 表名

                  RENAME 新表名;

      2. 增加字段

        ALTER TABLE 表名

                  ADD 字段名  数据类型 [完整性约束条件…],

                  ADD 字段名  数据类型 [完整性约束条件…];

        ALTER TABLE 表名

                  ADD 字段名  数据类型 [完整性约束条件…]  FIRST;  # 直接移到最前面

        ALTER TABLE 表名

                  ADD 字段名  数据类型 [完整性约束条件…]  AFTER 字段名;  # 选择插哪个字段的后面

      3. 删除字段

        ALTER TABLE 表名

                  DROP 字段名;

      4. 修改字段  # modify只能改字段数据类型完整约束,不能改字段名,但是change可以!

        ALTER TABLE 表名

                  MODIFY  字段名 数据类型 [完整性约束条件…];

        ALTER TABLE 表名

                  CHANGE 旧字段名 新字段名 新数据类型 [完整性约束条件…];

    2.复制表

    # 查询语句执行的结果也是一张表,可以看成虚拟表

    # 复制表结构+记录 (key不会复制: 主键、外键和索引)

    create table new_service select * from service;

    # 只复制表结构

    select * from service where 1=2;        //条件为假,查不到任何记录

    create table new1_service select * from service where 1=2;

    create table t4 like employees;

  • 相关阅读:
    Java中使用synchronized多线程同步的实例
    JDK中String类的intern方法实例
    Ubuntu APT按时间顺序排列已安装的软件包
    LinuxMint/LMDE 安装后的配置
    XLNX XC7Z020平台GIC中断示例程序
    吾八哥学k8s(四):kubernetes常用基本命令
    吾八哥学k8s(三):kubernetes里创建资源的方法
    gitlab-runner在Kubernetes环境下挂载宿主机目录的方法
    吾八哥学k8s(二):golang服务部署到kubernetes
    记Windows10下安装Docker的步骤
  • 原文地址:https://www.cnblogs.com/francis1/p/11384277.html
Copyright © 2011-2022 走看看