外键
什么是外键:让表与表有硬性层面上的关系
使用外键条件:1、表类型必须是InnoDB存储引擎。2、关联的字段即references指定的另外一个表的字段必须要唯一。
注意:1、创建表时必须先创建被关联表。2、插入数据时,也必须先插入被关联表数据。
一对多
案例1:部门和员工
思考:
- 一个部门可以有多个员工吗?可以
- 一个员工可以有多个部门吗?不可以
- 结论:部门与员工的关系是一对多。且外键创建在多的一方。
案例二:班级和学生
- 一个班级可以有多个学生吗?可以
- 一个学生可以有多个班级吗?不可以
- 结论:一对多,外键建立在多的一方即学生表里面。
案例三:老师和课程
- 一个课程可以有多个老师吗?可以。
- 一个老师可以有多个课程吗?不可以,一个老师只能教一门课程,语文老师不能同时也是数学老师,不专业。
- 结论:一对多,老师表里面应该设置外键。
只有一方可以一条数据对应对方的多条数据,这种关系叫做一对多。
''' 创建部门表: ''' create table department( id int primary key auto_increment, name varchar(20) not null, dep_desc varchar(200) ); ''' 创建员工表 ''' create table employee( id int primary key auto_increment, name varchar(20) not null, gender enum('male', 'female', 'others') default 'male', department_id int, foreign key(department_id) references department(id) on update cascade on delete cascade ); ''' 插入数据 ''’ insert into department(name, dep_desc) values('技术部', '技术部都是一群菜*'); insert into employee(name, gender, department_id) values('游哥', 'male', 1);
同步更新与同步删除:更新和删除操作都需要考虑关联与被关联的关系。这时候,出现级联操作
on update cascade
on delete cascade
删除部门后,对应的部门里面的员工表数据对应删除
更新部门后,对应员工表中的标示部门的字段同步更新
多对多
案例一:图书和作者
分析:
- 一本图书可以有多个作者吗?可以
- 一个作者可以有多本书吗? 完全可以!
- 结论:多对多,需要建立中间表。
案例二:老师和学生
- 一个老师可以有多个学生吗?可以
- 一个学生可以有多个老师吗?可以
- 结论:多对多
双方都能一条数据对应对方的多条数据,这种关系叫做多对多。
=====================创建表================= mysql> create table author( -> id int primary key auto_increment, -> name varchar(20)); Query OK, 0 rows affected (0.03 sec) mysql> create table book( -> id int primary key auto_increment, -> name varchar(20)); Query OK, 0 rows affected (0.03 sec) mysql> create table author_book( -> 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); Query OK, 0 rows affected (0.02 sec) =====================表详情================= mysql> desc author_book; +-----------+---------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-----------+---------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | author_id | int(11) | YES | MUL | NULL | | | book_id | int(11) | YES | MUL | NULL | | +-----------+---------+------+-----+---------+----------------+ 3 rows in set (0.00 sec) mysql> desc author; +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(20) | YES | | NULL | | +-------+-------------+------+-----+---------+----------------+ 2 rows in set (0.00 sec) mysql> desc book; +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(20) | YES | | NULL | | +-------+-------------+------+-----+---------+----------------+ 2 rows in set (0.00 sec) ==============================插入数据=================== mysql> insert into author(name) values('游哥'); Query OK, 1 row affected (0.00 sec) mysql> insert into author(name) values('鸡弟弟'); Query OK, 1 row affected (0.00 sec) mysql> insert into book(name) values('金瓶11111'); Query OK, 1 row affected (0.00 sec) mysql> insert into book(name) values('Python从入门到放弃'); Query OK, 1 row affected (0.00 sec) mysql> insert into author_book(author_id, book_id) values(1,1),(1,2),(2,1); Query OK, 3 rows affected (0.01 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> select * from author_book; +----+-----------+---------+ | id | author_id | book_id | +----+-----------+---------+ | 1 | 1 | 1 | | 2 | 1 | 2 | | 3 | 2 | 1 | +----+-----------+---------+ 3 rows in set (0.00 sec)
一对一
左表的一条记录唯一对应右表的一条记录,反之也一样。
格式:foreign key + unique
案例一:一个用户只有一个博客
create table user( id int primary key auto_increment, name varchar(20) ); create table blog( id int primary key auto_increment, blog_addr varchar(100), user_id int unique, foreign key(user_id) references user(id) ); mysql> desc blog; +-----------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-----------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | blog_addr | varchar(100) | YES | | NULL | | | user_id | int(11) | YES | UNI | NULL | | +-----------+--------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec) mysql> insert into user( -> name) values('游哥'); Query OK, 1 row affected (0.00 sec) mysql> insert into blog(blog_addr, user_id) values('上海', 1); Query OK, 1 row affected (0.01 sec) mysql> insert into blog(blog_addr, user_id) values('上海', 1); ERROR 1062 (23000): Duplicate entry '1' for key 'user_id' mysql> select * from blog; +----+-----------+---------+ | id | blog_addr | user_id | +----+-----------+---------+ | 1 | 上海 | 1 | +----+-----------+---------+ 1 row in set (0.00 sec)
修改表
1. 修改表名 ALTER TABLE 表名 RENAME 新表名; alter table user rename userinfo; 2. 增加字段 ALTER TABLE 表名 ADD 字段名 数据类型 [完整性约束条件…], ADD 字段名 数据类型 [完整性约束条件…]; mysql> alter table userinfo add gender enum('male', 'female') default 'male'; mysql> desc userinfo; +--------+-----------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------+-----------------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(20) | YES | | NULL | | | gender | enum('male','female') | YES | | male | | +--------+-----------------------+------+-----+---------+----------------+ ALTER TABLE 表名 ADD 字段名 数据类型 [完整性约束条件…] FIRST; ALTER TABLE 表名 ADD 字段名 数据类型 [完整性约束条件…] AFTER 字段名; 3. 删除字段 ALTER TABLE 表名 DROP 字段名; mysql> alter table userinfo drop gender; 4. 修改字段 # modify只能改字段数据类型完整约束,不能改字段名,但是change可以! ALTER TABLE 表名 MODIFY 字段名 数据类型 [完整性约束条件…]; ALTER TABLE 表名 CHANGE 旧字段名 新字段名 旧数据类型 [完整性约束条件…]; ALTER TABLE 表名 CHANGE 旧字段名 新字段名 新数据类型 [完整性约束条件…];
复制表
# 查询语句执行的结果也是一张表,可以看成虚拟表 # 复制表结构+记录 (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; mysql> create table user( -> id int primary key auto_increment, -> name varchar(10)); Query OK, 0 rows affected (0.03 sec) mysql> create table userinfo like user; Query OK, 0 rows affected (0.02 sec) mysql> desc userinfo; +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(10) | YES | | NULL | | +-------+-------------+------+-----+---------+----------------+ 2 rows in set (0.00 sec) mysql> desc user; +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(10) | YES | | NULL | | +-------+-------------+------+-----+---------+----------------+ 2 rows in set (0.00 sec)