引子:把所有数据都存放于一张表的弊端
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',) """