zoukankan      html  css  js  c++  java
  • Mysql 表与表之间的关系

    一、前言

    研究表与表之间的关系前,先要知道将所有数据存放在一张表中的弊端:
    1.结构不清晰 ---> 不致命
    2.浪费空间 ---> 不致命
    3.可扩展性极差 ---> 不可忽视的弊端

    就i好比将所有的代码存放在一个文件中,强耦合到了一起,而我们需要做的就是 ----> 解耦合 ----> 拆分表

    拆分表解决以上问题.
    需要给两张表之间,建立一种强有力的关系, 使用 “外键”。

    foreign key(外键): 用来建立两张表之间的关系

    • 一对多
    • 多对多
    • 一对一

    foreign key(外键)语法:
    foreign key(当前表中建立关系的外键字段) references 被关联表名(id)

    二、表与表之间的关系

    (一) 一对多

    一对多(左边表的多条记录对应右边表的唯一一条记录)

    注意:必须先建立被关联表,再建立关联表

    例如:定义一张员工部门表
    id,name,gender,dep_name

    注意: 要确定两张表之间的关系,必须站在两个位置去思考:是否是单向多对一还是双向多对一,还是一一对应的关系。

    1. 站在员工表的位置:多个员工能否对应一个部门?(能)
      员工与部门:多对一(员工表单向 多对一 部门表)

    2. 站在部门表的位置:多个部门能否对应一个员工?(不能)

    总结:凡是单向 多对一的表关系,称之为 一对多 的外键关系,如下图所示

    在这里插入图片描述

    创建两张表:
    
    #被关联表:
    dep:
    	create table dep(
    		id int primary key auto_increment,
    		dep_name varchar(16),
    		dep_desc varchar(255));
    
    #关联表:
    emp:	
    	create table emp(
    		id int primary key auto_increment,
    		name varchar(6),
    		age int,
    		gender enum('male','female'),
    		dep_id int not null,
    		foreign key(dep_id) references dep(id));
    
    #插入数据:必须先插入被关联表(dep)的数据,再插入关联表(emp)的数据。
    
    #插入dep的数据:
    insert into dep(dep_name,dep_desc) values(
    'nb_外交部', '国际形象大使部门'),
    ('sb_教学部', '造程序员部门!!!!'),
    ('技术部', '技术有限部门');
    
    #插入emp的数据:
    insert into emp(name, age, gender, dep_id)
    values('tank', 17, 'male', 1),
    ('jason', 70, 'male', 2),
    ('sean', 50, 'male', 2),
    ('egon', 88, 'male', 2),
    ('owen', 95, 'female', 3);
    
    # 报错
    insert into emp(name, age, gender, dep_id) values(
    'baohan', 18, 'others', 999);   
    
    
    更新数据:
    update emp set dep_id=100 where id=2;  #报错
    update dep set id=100 where id=1; #报错
    
    # 要先删除已关联的dep_id字段,才能修改dep表中的关联id字段。
    delete from emp where id=1;
    update dep set id=100 where id=1;
    
    mysql> select * from emp;
    +----+-------+------+--------+--------+
    | id | name  | age  | gender | dep_id |
    +----+-------+------+--------+--------+
    |  2 | jason |   70 | male   |      2 |
    |  3 | sean  |   50 | male   |      2 |
    |  4 | egon  |   88 | male   |      2 |
    |  5 | owen  |   95 | female |      3 |
    +----+-------+------+--------+--------+
    mysql> select * from dep;
    +-----+--------------+--------------------------+
    | id  | dep_name     | dep_desc                 |
    +-----+--------------+--------------------------+
    |   2 | sb_教学部    | 造程序员部门!!!!         |
    |   3 | 技术部       | 技术有限部门             |
    | 100 | nb_外交部    | 国际形象大使部门         |
    +-----+--------------+--------------------------+
    
    
    
    删除:先删除关联表中的记录,再删除被关联表中的记录
    #先删除emp表中的dep_id为2的记录
    delete from emp where dep_id=2;
    #再删除dep表中id为2的记录
    delete from dep where id=2;
    
    mysql> select * from emp;
    +----+------+------+--------+--------+
    | id | name | age  | gender | dep_id |
    +----+------+------+--------+--------+
    |  5 | owen |   95 | female |      3 |
    +----+------+------+--------+--------+
    mysql> select * from dep;
    +-----+--------------+--------------------------+
    | id  | dep_name     | dep_desc                 |
    +-----+--------------+--------------------------+
    |   3 | 技术部       | 技术有限部门             |
    | 100 | nb_外交部    | 国际形象大使部门         |
    +-----+--------------+--------------------------+
    

    在这里插入图片描述
    在这里插入图片描述

    级联更新与级联删除

    • on update cascade 级联更新
    • on delete cascade 级联删除

    意思是 当更新或删除主键表时,那么外键表也会跟随一起更新或删除

    再以上述例子为例:

    创建两张表:
    
    #被关联表:
    dep:
    	create table dep(
    		id int primary key auto_increment,
    		dep_name varchar(16),
    		dep_desc varchar(255));
    
    #关联表:
    emp:	
        create table emp(
            id int primary key auto_increment,
            name varchar(6),
            age int,
            gender enum('male', 'female'),
            dep_id int not null,
            foreign key(dep_id) references dep(id)
            on update cascade
            on delete cascade
        );
    		
    
    #插入数据:必须先插入被关联表(dep)的数据,再插入关联表(emp)的数据。
    
    #插入dep的数据:
    insert into dep(dep_name,dep_desc) values(
    'nb_外交部', '国际形象大使部门'),
    ('sb_教学部', '造程序员部门!!!!'),
    ('技术部', '技术有限部门');
    
    #插入emp的数据:
    insert into emp(name, age, gender, dep_id)
    values('tank', 17, 'male', 1),
    ('jason', 70, 'male', 2),
    ('sean', 50, 'male', 2),
    ('egon', 88, 'male', 2),
    ('owen', 95, 'female', 3);
    
    更新数据或删除数据:
    #更新记录:
    update dep set id=200 where id=1;
    
    mysql> select * from dep;
    +-----+--------------+--------------------------+
    | id  | dep_name     | dep_desc                 |
    +-----+--------------+--------------------------+
    |   2 | sb_教学部    | 造程序员部门!!!!         |
    |   3 | 技术部       | 技术有限部门             |
    | 200 | nb_外交部    | 国际形象大使部门         |
    +-----+--------------+--------------------------+
    
    #删除记录
    delete from dep where id=200;
    
    mysql> select * from dep;
    +----+--------------+------------------------+
    | id | dep_name     | dep_desc               |
    +----+--------------+------------------------+
    |  2 | sb_教学部    | 造程序员部门!!!!       |
    |  3 | 技术部       | 技术有限部门           |
    +----+--------------+------------------------+
    

    (二) 一对一

    一对一:两张之间的关系 一一对应,将一张数据量比较大的表,拆分成两张表。

    例如:数据量比较大的用户表

    • 用户表:多个用户 能否 对应 一个用户详情信息? 不能
    • 用户详情表:多个用户详情信息 能否 对应 一个用户? 不能

    两张表之间都没有多对一的关系,就是“一对一”的外键关系。

    • 总表:user_info
      id, name, age, gender, hobby, id_card

    • 分表:user:
      id , name, age, detail_id(外键)

    • 分表:detail:
      id, gender, hobby, id_card

    注意:1、user与detail表建立了 一对一的外键 关系。
    2、foreign key 应该建在 使用频率较高的一方。
    在这里插入图片描述

    创建表:
    #被关联表
    detail
    	create table detail(
    		id int primary key auto_increment,
    		gender enum('male', 'female'),
    		hobby varchar(32),
    		id_card char(18)
    		);
    	
    #关联表
    user
    	create table user(
    		id int primary key auto_increment,
    		name varchar(6),
    		age int,
    		detail_id int unique,
    		foreign key(detail_id) references detail(id)
    		on update cascade
    		on delete cascade
    		);
    
    	
    
    #插入数据
    insert into detail(gender, hobby,id_card) values
    ('male','play ball',9527),
    ('female','rap',909),
    ('female','吃鸡',101),
    ('female','被吃鸡',404),
    ('female','HSNM',500
    );
    
    insert into user(name,age,detail_id) values
    ('tank', 17,3),
    ('egon', 77,5),
    ('jason', 87,1),
    ('sean', 97,2),
    ('owen', 107,4);
    
    # 报错,一对一,关系必须 一一对应
    insert into user(name,age,detail_id) values ('baohan',19,3);
    
    mysql> select * from user;
    +----+-------+------+-----------+
    | id | name  | age  | detail_id |
    +----+-------+------+-----------+
    | 1 | tank  |   17 |         3 |
    | 2 | egon  |   77 |         5 |
    | 3 | jason |   87 |         1 |
    | 4 | sean  |   97 |         2 |
    | 5 | owen  |  107 |         4 |
    +----+-------+------+-----------+
    
    mysql> select * from detail;
    +----+--------+-----------+---------+
    | id | gender | hobby     | id_card |
    +----+--------+-----------+---------+
    |  1 | male   | play ball | 9527    |
    |  2 | female | rap       | 909     |
    |  3 | female | 吃鸡      | 101     |
    |  4 | female | 被吃鸡    | 404     |
    |  5 | female | HSNM      | 500     |
    +----+--------+-----------+---------+
    
    

    (三) 多对多

    多对多:一个作者可以写多本书,一本书也可以有多个作者,双向的一对多,即 多对多的外键关系

    关联方式:foreign key + 一张新的表
    要把book_id和author_id设置成唯一

    在这里插入图片描述

    - 多对多:
        也必须站在两张表的位置去思考;
    
        - 错误示范:
       
            - 创建book表
                create table book(
                    id int primary key auto_increment,
                    title varchar(20),
                    price int,
                    book_content varchar(255),
                    author_id int,
                    foreign key(author_id) references author(id)
                    on update cascade
                    on delete cascade
                );
    
            - 创建author表
                create table author(
                    id int primary key auto_increment,
                    name varchar(16),
                    age int,
                    book_id int,
                    foreign key(book_id) references book(id)
                    on update cascade
                    on delete cascade
                );
    
    - 问题: 无法知道哪张表是被关联表
    

    正确示范:
    	- 利用第三张表,为两张表建立“多对多外键关系”。
    book:
        create table book(
            id int primary key auto_increment,
            title varchar(20),
            price int,
            book_content varchar(255));
    
    author:
        create table author(
            id int primary key auto_increment,
            name varchar(16),
            age int);
    
    book2author:
        create table book2author(
            id int primary key auto_increment,
            book_id int,
            author_id int,
            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
             );
    
    #插入数据
    - book
        insert into book(title, price, book_content) values
        ('金瓶mei', 199, '讲述朦胧时光的小故事'),
        ('python从入门到断气', 2000, '学习如何一夜秃头'),
        ('三体', 200, '跟着大佬进入宇宙奇幻世界');
        
    - author
        insert into author(name, age) values
        ('egon', 68),
        ('jason', 88);
        
    - book2author:
    	insert into book2author(book_id, author_id) values
        (1, 1),
        (1, 2),
        (2, 2),
        (3, 1);
    
    # 报错, 插入的数据,book_id, author_id必须存在
    insert into book2author(book_id, author_id) values (4, 4);
    
    
    # 更新或删除
    # 更新
        - update book set price=6666 where id=1;
        - update book set id=4 where id=1;
    # 删除
        - delete from book where id=4;
    
  • 相关阅读:
    黑马程序员-block代码块和protocol协议
    黑马程序员-内存管理之autorelease和ARC机制
    黑马程序员-内存管理之set方法内存管理, property参数,循环引用。
    黑马程序员-内存管理之引用计数器
    黑马程序员-构造方法
    黑马程序员-@property,@synthesize使用细节和id
    黑马程序员—OC点语法和成员变量作用域
    黑马程序员-c语言指针的学习
    黑马程序员-OC基本语法
    NSSearchPathForDirectoriesInDomains用法 (转)
  • 原文地址:https://www.cnblogs.com/baohanblog/p/12144007.html
Copyright © 2011-2022 走看看