外键(FOREIGN KEY)

引子:把所有数据都存放于一张表的弊端

    1、表的组织结构复杂不清晰 
    2、浪费空间 
    3、扩展性极差 

为了解决上述的问题,就需要用多张表来存放数据。

表与表的记录之间存在着三种关系:一对多、多对多、一对一的关系。

处理表之间关系问题就会利用到FOREIGN KEY

多对一关系:

被关联表称为主表,关联表称为子表

子表通过foreign key 关联主表,子表多条记录可以关联主表一条记录

示例如下:

mysql> show create table dep;  #主表
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                       |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| dep   | CREATE TABLE `dep` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `dep_name` char(10) DEFAULT NULL,
  `dep_comment` char(60) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

mysql> show create table emp;
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                          |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| emp   | CREATE TABLE `emp` (  #子表
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` char(16) CHARACTER SET latin1 DEFAULT NULL,
  `gender` enum('male','female') CHARACTER SET latin1 NOT NULL DEFAULT 'male',
  `dep_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `dep_id` (`dep_id`),
  CONSTRAINT `emp_ibfk_1` FOREIGN KEY (`dep_id`) REFERENCES `dep` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> 
mysql> insert into dep(dep_name,dep_comment) values ('教学部','辅助学生学习,教授课程'),('公关部','处理危机公关'),('技术部','开发项目,研究技术');
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> insert into emp(name,gender,dep_id)  values ('monicx0','male',1), ('monicx1','male',2), ('monicx2','male',1), ('monicx3','male',1), ('lili','female',3);
Query OK, 5 rows affected (0.00 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql> select * from dep;
+----+-----------+---------------------------------+
| id | dep_name  | dep_comment                     |
+----+-----------+---------------------------------+
|  1 | 教学部    | 辅助学生学习,教授课程           |
|  2 | 公关部    | 处理危机公关                    |
|  3 | 技术部    | 开发项目,研究技术               |
|  4 | 教学部    | 辅助学生学习,教授课程           |
|  5 | 公关部    | 处理危机公关                    |
|  6 | 技术部    | 开发项目,研究技术               |
+----+-----------+---------------------------------+
6 rows in set (0.00 sec)

mysql> select * from emp;
+----+---------+--------+--------+
| id | name    | gender | dep_id |
+----+---------+--------+--------+
|  1 | monicx0 | male   |      1 |
|  2 | monicx1 | male   |      2 |
|  3 | monicx2 | male   |      1 |
|  4 | monicx3 | male   |      1 |
|  5 | lili    | female |      3 |
|  6 | monicx0 | male   |      1 |
|  7 | monicx1 | male   |      2 |
|  8 | monicx2 | male   |      1 |
|  9 | monicx3 | male   |      1 |
| 10 | lili    | female |      3 |
+----+---------+--------+--------+
10 rows in set (0.00 sec)

mysql> 

修改主表记录查看影响:

mysql> update dep set id=99 where id=3;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from dep;
+----+-----------+---------------------------------+
| id | dep_name  | dep_comment                     |
+----+-----------+---------------------------------+
|  1 | 教学部    | 辅助学生学习,教授课程           |
|  2 | 公关部    | 处理危机公关                    |
|  4 | 教学部    | 辅助学生学习,教授课程           |
|  5 | 公关部    | 处理危机公关                    |
|  6 | 技术部    | 开发项目,研究技术               |
| 99 | 技术部    | 开发项目,研究技术               |
+----+-----------+---------------------------------+
6 rows in set (0.00 sec)

mysql> select * from emp;
+----+---------+--------+--------+
| id | name    | gender | dep_id |
+----+---------+--------+--------+
|  1 | monicx0 | male   |      1 |
|  2 | monicx1 | male   |      2 |
|  3 | monicx2 | male   |      1 |
|  4 | monicx3 | male   |      1 |
|  5 | lili    | female |     99 |
|  6 | monicx0 | male   |      1 |
|  7 | monicx1 | male   |      2 |
|  8 | monicx2 | male   |      1 |
|  9 | monicx3 | male   |      1 |
| 10 | lili    | female |     99 |
+----+---------+--------+--------+
10 rows in set (0.00 sec)

mysql> 
mysql> delete from dep where id=1;
Query OK, 1 row affected (0.00 sec)

mysql> select * from dep;
+----+-----------+---------------------------------+
| id | dep_name  | dep_comment                     |
+----+-----------+---------------------------------+
|  2 | 公关部    | 处理危机公关                    |
|  4 | 教学部    | 辅助学生学习,教授课程           |
|  5 | 公关部    | 处理危机公关                    |
|  6 | 技术部    | 开发项目,研究技术               |
| 99 | 技术部    | 开发项目,研究技术               |
+----+-----------+---------------------------------+
5 rows in set (0.00 sec)

mysql> select * from emp;
+----+---------+--------+--------+
| id | name    | gender | dep_id |
+----+---------+--------+--------+
|  2 | monicx1 | male   |      2 |
|  5 | lili    | female |     99 |
|  7 | monicx1 | male   |      2 |
| 10 | lili    | female |     99 |
+----+---------+--------+--------+
4 rows in set (0.00 sec)

mysql> 

多对多关系:

多对多关系就是A,B 两张表,A 表的一条记录可以关联B表的多个条记录 ,B表的一条记录也可以关联A 表的多条记录。

mysql> show create table authorG
*************************** 1. row ***************************
Table: author
Create Table: CREATE TABLE `author` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` char(16) CHARACTER SET latin1 DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> show create table bookG
*************************** 1. row ***************************
Table: book
Create Table: CREATE TABLE `book` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`book_name` varchar(16) DEFAULT NULL,
`price` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql>

insert into author(name) values
('monicx1'),
('monicx2'),
('monicx3')
;
insert into book(book_name,price) values
('python从入门到入土',200),
('liunx从入门到入土',400),
('java从入门到入土',300),
('php从入门到入土',100)
;
#建立第三张表:
create table author2book(
    id int primary key auto_increment,
    author_id int,
    book_id int,
    foreign key(author_id) references author(id)
    on update cascade
    on delete cascade,
    foreign key(book_id) references book(id)
    on update cascade
    on delete cascade
);
 
insert into author2book(author_id,book_id) values
(1,3),
(1,4),
(2,2),
(2,4),
(3,1),
(3,2);
mysql> select * from author2book;
+----+-----------+---------+
| id | author_id | book_id |
+----+-----------+---------+
|  3 |         2 |       2 |
|  4 |         2 |       4 |
|  5 |         3 |       1 |
+----+-----------+---------+
3 rows in set (0.00 sec)

mysql> select * from book;
+----+--------------------------+-------+
| id | book_name                | price |
+----+--------------------------+-------+
|  1 | python从入门到入土       |   200 |
|  2 | liunx从入门到入土        |   400 |
|  3 | java从入门到入土         |   300 |
|  4 | php从入门到入土          |   100 |
+----+--------------------------+-------+
4 rows in set (0.00 sec)

mysql> delete from book where id=2;
Query OK, 1 row affected (0.00 sec)

mysql> select * from author2book;    #主表的操作都会影响关联的子表,因为我们配置了  caseade
+----+-----------+---------+
| id | author_id | book_id |
+----+-----------+---------+
|  4 |         2 |       4 |
|  5 |         3 |       1 |
+----+-----------+---------+
2 rows in set (0.00 sec)

mysql> 

一对一关系:

左表的一条记录唯一对应右表的一条记录,反之也一样

create table customer(
    id int primary key auto_increment,
    name char(20) not null,
    qq char(10) not null,
    phone char(16) not null
);
 
create table student(
    id int primary key auto_increment,
    class_name char(20) not null,
    customer_id int unique, #该字段一定要是唯一的
    foreign key(customer_id) references customer(id) #此时外键的字段一定要保证unique
    on delete cascade
    on update cascade
);

ORM 

#多表操作,一对一模型
#先建立主表,再建立子表,子表关联主表。
class AuthorDetail(models.Model):
    nid = models.AutoField(primary_key=True)
    birthday=models.DateField()
    telephone=models.CharField(max_length=11)
    addr=models.CharField(max_length=64)

class Author(models.Model):
    nid=models.AutoField(primary_key=True)
    name=models.CharField(max_length=32)
    age=models.IntegerField()
#建立一对一联级
    ad_chain=models.OneToOneField(to='AuthorDetail',on_delete=models.CASCADE)
#
class Publish(models.Model):
    nid=models.AutoField(primary_key=True)
    name=models.CharField(max_length=32)
    city=models.CharField(max_length=32)
    email=models.EmailField()

class NewBook(models.Model):

    nid=models.AutoField(primary_key=True)
    book_name=models.CharField(max_length=32)
    price=models.DecimalField(max_digits=5,decimal_places=2)
    #建立一对多关系,外键字段在多的一方,一个出版社可以出版多本书
    publish=models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)
    #建立多对多关系,一个作者可以对应多本书,一本书可以对应过个作者,会自动创建第三章表
    author=models.ManyToManyField(to='Author',)
"""
原文地址:https://www.cnblogs.com/zy09/p/13739616.html