zoukankan      html  css  js  c++  java
  • 数据库开发——MySQL——foreign key

    五,foreign key

    foreign key是跟外部表关联的字段。

    foreign key理解

    学生信息表有三个字段:学号、姓名、年级,学校有四个年级,但是有3万多学生,那就意味着年级这个字段的信息要重复存储,要存储的年级信息越长就越浪费资源。

    可以通过定义一个年级表关联学生信息表,这样每个学生的年级就只需要存储所处年级在年级信息表中的id,这个外表关联关系,就是通过foreign key定义的。

    既然学生的年级信息要关联到年级信息,所以在创建学生信息表之前年级信息表必须存在,也就是必须先创建年级信息表,并且表的类型必须是innodb存储引擎,且被关联的字段必须是另一个表中的unique字段。

    create table grade(
    	grade_year year primary key,
    	name varchar(20) not null
    	)engine=innodb;
    
    create table student(
    	id int primary key,
    	name varchar(20) not null,
    	grade_id year,
    	constraint fk_grade_id foreign key(grade_id) references grade(grade_year)
    	on delete cascade	# 同步删除
    	on update cascade	# 同步更新
    
    insert into grade values 
    	(2019, "2019 grade"), 
    	(2018, "2018 grade"), 
    	(2017, "2017 grade"), 
    	(2016, "2016 grade");
    
    insert into student values
    	(1, "Alex", 2018),
    	(2, "Coco", 2019),
    	(3, "alex", 2018),
    	(4, "coco", 2019);
    
    select * from student;
    select * from grade;
    
    delete from grade where grade_year=2019;
    select * from student;
    
    update grade set grade_year=2019 where grade_year=2018;
    select * from student;
    

    执行结果为:

    mysql> create table grade(
        -> grade_year year primary key,
        -> name varchar(20) not null
        -> )engine=innodb;
    Query OK, 0 rows affected (0.85 sec)
    
    mysql> create table student(
        -> id int primary key,
        -> name varchar(20) not null,
        -> grade_id year,
        -> constraint fk_grade_id foreign key(grade_id) references grade(grade_year)
        -> on delete cascade
        -> on update cascade
        -> )engine=innodb;
    Query OK, 0 rows affected (0.66 sec)
    
    mysql> insert into grade values (2019, "2019 grade"), (2018, "2018 grade"), (2017, "2017 grade"), (2016, "2016 grade");
    Query OK, 4 rows affected (0.15 sec)
    Records: 4  Duplicates: 0  Warnings: 0
    
    mysql> insert into student values
        -> (1, "Alex", 2018),
        -> (2, "Coco", 2019),
        -> (3, "alex", 2018),
        -> (4, "coco", 2019);
    Query OK, 4 rows affected (0.22 sec)
    Records: 4  Duplicates: 0  Warnings: 0
    
    mysql> select * from student;
    +----+------+----------+
    | id | name | grade_id |
    +----+------+----------+
    |  1 | Alex |     2018 |
    |  2 | Coco |     2019 |
    |  3 | alex |     2018 |
    |  4 | coco |     2019 |
    +----+------+----------+
    4 rows in set (0.00 sec)
    
    mysql> select * from grade;
    +------------+------------+
    | grade_year | name       |
    +------------+------------+
    |       2016 | 2016 grade |
    |       2017 | 2017 grade |
    |       2018 | 2018 grade |
    |       2019 | 2019 grade |
    +------------+------------+
    4 rows in set (0.00 sec)
    
    mysql> delete from grade where grade_year=2019;
    Query OK, 1 row affected (0.27 sec)
    
    mysql> select * from student;
    +----+------+----------+
    | id | name | grade_id |
    +----+------+----------+
    |  1 | Alex |     2018 |
    |  3 | alex |     2018 |
    +----+------+----------+
    2 rows in set (0.00 sec)
    
    mysql> update grade set grade_year=2019 where grade_year=2018;
    Query OK, 1 row affected (0.07 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    mysql> select * from student;
    +----+------+----------+
    | id | name | grade_id |
    +----+------+----------+
    |  1 | Alex |     2019 |
    |  3 | alex |     2019 |
    +----+------+----------+
    2 rows in set (0.00 sec)
    

    如何找出两表之间的关系

    分析步骤:

    1、先站在左表的角度去找

    是否左表的多条记录可以对应右表的一条记录,如果是,则证明左表的一个字段foreign key 右表一个字段(通常是id)
    

    2、再站在右表的角度去找

    是否右表的多条记录可以对应左表的一条记录,如果是,则证明右表的一个字段foreign key 左表一个字段(通常是id)
    

    3、总结:

    #多对一:
    如果只有步骤1成立,则是左表多对一右表
    如果只有步骤2成立,则是右表多对一左表
    
    #多对多
    如果步骤1和2同时成立,则证明这两张表时一个双向的多对一,即多对多,需要定义一个这两张表的关系表来专门存放二者的关系
    
    #一对一:
    如果1和2都不成立,而是左表的一条记录唯一对应右表的一条记录,反之亦然。这种情况很简单,就是在左表foreign key右表的基础上,将左表的外键字段设置成unique即可
    

    建立两表之间的关系

    三张表:出版社,作者信息,书

    一对多或多对一

    一对多(或多对一):一个出版社可以出版多本书

    关联方式:foreign key

    create table press(
    	id int primary key auto_increment,
    	name varchar(20));
    
    create table book(
    	id int primary key auto_increment,
    	name varchar(20),
    	press_id int not null,
    	foreign key(press_id) references press(id)
    	on delete cascade
    	on update cascade);
    
    
    insert into press(name) values
    	('北京工业地雷出版社'),
    	('人民音乐不好听出版社'),
    	('知识产权没有用出版社');
    
    insert into book(name,press_id) values
    	('九阳神功',1),
    	('九阴真经',2),
    	('九阴白骨爪',2),
    	('独孤九剑',3),
    	('降龙十巴掌',2),
    	('葵花宝典',3);
    
    select * from press;
    
    select * from book;
    

    执行结果为:

    mysql> create table press(
    	id int primary key auto_increment,
    	name varchar(20));
    
    mysql> create table book(
        -> id int primary key auto_increment,
        -> name varchar(20),
        -> press_id int not null,
        -> foreign key(press_id) references press(id)
        -> on delete cascade
        -> on update cascade);
    Query OK, 0 rows affected (0.50 sec)
    
    mysql> insert into press(name) values
        -> ('北京工业地雷出版社'),
        -> ('人民音乐不好听出版社'),
        -> ('知识产权没有用出版社');
    Query OK, 3 rows affected (0.18 sec)
    Records: 3  Duplicates: 0  Warnings: 0
    
    mysql> insert into book(name,press_id) values
        -> ('九阳神功',1),
        -> ('九阴真经',2),
        -> ('九阴白骨爪',2),
        -> ('独孤九剑',3),
        -> ('降龙十巴掌',2),
        -> ('葵花宝典',3);
    Query OK, 6 rows affected (0.10 sec)
    Records: 6  Duplicates: 0  Warnings: 0
    
    mysql> select * from press;
    +----+--------------------------------+
    | id | name                           |
    +----+--------------------------------+
    |  1 | 北京工业地雷出版社             |
    |  2 | 人民音乐不好听出版社           |
    |  3 | 知识产权没有用出版社           |
    +----+--------------------------------+
    3 rows in set (0.00 sec)
    
    mysql> select * from book;
    +----+-----------------+----------+
    | id | name            | press_id |
    +----+-----------------+----------+
    |  1 | 九阳神功        |        1 |
    |  2 | 九阴真经        |        2 |
    |  3 | 九阴白骨爪      |        2 |
    |  4 | 独孤九剑        |        3 |
    |  5 | 降龙十巴掌      |        2 |
    |  6 | 葵花宝典        |        3 |
    +----+-----------------+----------+
    6 rows in set (0.00 sec)
    Query OK, 0 rows affected (0.62 sec)
    

    多堆多

    多对多:一个作者可以写多本书,一本书也可以有多个作者,双向的一对多,即多对多
      
    关联方式:foreign key+一张新的表

    create table author(
    	id int primary key auto_increment,
    	name varchar(20));
    
    create table author2book(
    	id int not null unique auto_increment,
    	author_id int not null,
    	book_id int not null,
    	constraint fk_author foreign key(author_id) references author(id)
    	on delete cascade
    	on update cascade,
    	constraint fk_book foreign key(book_id) references book(id)
    	on delete cascade
    	on update cascade,
    	primary key(author_id,book_id));
    
    insert into author(name) values('Alex'),('Coco'),('BeiBei'),('Python');
    
    insert into author2book(author_id,book_id) values
    (1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(2,1),(2,6),(3,4),(3,5),(3,6),(4,1);
    
    select * from author;
    select * from author2book;
    select * from book;
    

    执行结果为:

    mysql> create table author(
        -> id int primary key auto_increment,
        -> name varchar(20));
    Query OK, 0 rows affected (0.52 sec)
    
    mysql> create table author2book(
        -> id int not null unique auto_increment,
        -> author_id int not null,
        -> book_id int not null,
        -> constraint fk_author foreign key(author_id) references author(id)
        -> on delete cascade
        -> on update cascade,
        -> constraint fk_book foreign key(book_id) references book(id)
        -> on delete cascade
        -> on update cascade,
        -> primary key(author_id,book_id));
    Query OK, 0 rows affected (0.60 sec)
    
    mysql> insert into author(name) values('Alex'),('Coco'),('BeiBei'),('Python');
    Query OK, 4 rows affected (0.08 sec)
    Records: 4  Duplicates: 0  Warnings: 0
    
    mysql>
    mysql> insert into author2book(author_id,book_id) values
        -> (1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(2,1),(2,6),(3,4),(3,5),(3,6),(4,1);
    Query OK, 12 rows affected (0.06 sec)
    Records: 12  Duplicates: 0  Warnings: 0
    
    mysql> select * from author;
    +----+--------+
    | id | name   |
    +----+--------+
    |  1 | Alex   |
    |  2 | Coco   |
    |  3 | BeiBei |
    |  4 | Python |
    +----+--------+
    4 rows in set (0.00 sec)
    
    mysql> select * from author2book;
    +----+-----------+---------+
    | id | author_id | book_id |
    +----+-----------+---------+
    |  1 |         1 |       1 |
    |  2 |         1 |       2 |
    |  3 |         1 |       3 |
    |  4 |         1 |       4 |
    |  5 |         1 |       5 |
    |  6 |         1 |       6 |
    |  7 |         2 |       1 |
    |  8 |         2 |       6 |
    |  9 |         3 |       4 |
    | 10 |         3 |       5 |
    | 11 |         3 |       6 |
    | 12 |         4 |       1 |
    +----+-----------+---------+
    12 rows in set (0.00 sec)
    
    mysql> select * from book;
    +----+-----------------+----------+
    | id | name            | press_id |
    +----+-----------------+----------+
    |  1 | 九阳神功        |        1 |
    |  2 | 九阴真经        |        2 |
    |  3 | 九阴白骨爪      |        2 |
    |  4 | 独孤九剑        |        3 |
    |  5 | 降龙十巴掌      |        2 |
    |  6 | 葵花宝典        |        3 |
    +----+-----------------+----------+
    6 rows in set (0.00 sec)
    
  • 相关阅读:
    织梦开发——相关阅读likeart应用
    织梦标签教程
    织梦专题调用代码
    HIT 2543 Stone IV
    POJ 3680 Intervals
    HIT 2739 The Chinese Postman Problem
    POJ 1273 Drainage Ditches
    POJ 2455 Secret Milking Machine
    SPOJ 371 Boxes
    HIT 2715 Matrix3
  • 原文地址:https://www.cnblogs.com/AlexKing007/p/12337975.html
Copyright © 2011-2022 走看看