实际开发中,一个项目通常需要很多张表才能完成。例如:一个商城项目就需要分类表(category)、商品表(products)、订单表(orders)等多张表。且这些表的数据之间存在一定的关系,接下来我们将在单表的基础上,一起学习多表方面的知识。
MySQL多表之间的关系可以概括为:一对一、一对多/多对一关系,多对多
任一表中添加唯一外键,指向另一方主键,确保一对一关系
一般一对一关系很少见,遇到一对一关系的表最好是合并表
部门和员工
分析:一个部门有多个员工,一个员工只能对应一个部门
实现原则:在多的一方建立外键,指向一的一方的主键
学生和课程
分析:一个学生可以选择很多门课程,一个课程也可以被很多学生选择
原则:多对多关系实现需要借助第三张中间表。中间表至少包含两个字段,将多对多的关系,拆成一对多的关系,中间表至少要有两个外键。这两个外键分别指向原来的那两张表的主键
MySQL外键约束(FOREIGN KEY)是表的一个特殊字段,经常与主键约束一起使用。对于两个具有关联关系的表而言,相关联字段中主键所在的表就是主表(父表),外键所在的表就是从表(子表)
特点:
定义一个外键时,需要遵守下列规则:
主表必须已经存在于数据库中,或者是当前正在创建的表。
必须为主表定义主键。
主键不能包含空值,但允许在外键中出现空值。也就是说,只要外键的每个非空值出现在指定的主键中,这个外键的内容就是正确的。
在主表的表名后面指定列名或列名的组合。这个列或列的组合必须是主表的主键或候选键。
外键中列的数目必须和主表的主键中列的数目相同。
外键中列的数据类型必须和主表主键中对应列的数据类型相同。
在create table语句中,通过foreign key关键字来指定外键,具体的语法格式如下:
[constraint <外键名>] foreign key [字段名 1,字段名2, ...] references <主表名> [主键列1,主键列2,...]
create table if not exists dept(
detpno varchar(20) primary key,
name varchar(20)
);
create table if not exists emp(
eid varchar(20) primary key,
ename varchar(20),
age int,
dept_id varchar(20),
constraint emp_fk foreign key(dept_id) references dept(detpno)
);
外键约束也可以在修改表时添加,但是添加外键约束的前提是:从表中外键列中的数据必须与主表中主键列中的数据一致或者是没有数据。
alter table<数据表名> add constraint <外键名> foreign key (<列名>) references <主表名>(<列名>);
create table if not exists dept2(
detpno varchar(20) primary key,
name varchar(20)
);
create table if not exists emp2(
eid varchar(20) primary key,
ename varchar(20),
age int,
dept_id varchar(20)
);
alter table emp2 add constraint emp2_fk foreign key(dept_id) references dept2(detpno);
insert into dept values('1001','研发部');
insert into dept values('1002','销售部');
insert into dept values('1003','财务部');
insert into dept values('1004','人事部');
insert into emp values('7','湫',50,'1003');
insert into emp values('8','天山童姥',60,'1005');--不可以
删除数据:
注意:
1:主表的数据被从表依赖时,不能删除,否则可以删除
2:从表的数据可以随便删除
delete from dept where detpno='1001'; --不可以删除
delete from dept where detpno='1004'; --可以删除
delete from emp where eid='7'; --可以删除
当一个表中不需要外键约束时,就需要从表中将其删除。外键一旦删除,就会解除主表和从表间的关联关系
格式:
alter table<表名> drop foreign key <外键约束名>;
alter table emp2 drop foreign key emp2_fk;
多对多关系
修改和删除时,中间从表可以随便删除和修改,但是两边的主表受从表依赖的数据不能删除或者修改
多表查询就是同时查询两个或两个以上的表,因为有的时候用户在查看数据的时候需要显示的数据来自多张表.多表查询有以下分类:
1)交叉连接查询[产生笛卡尔积,了解]
语法: select * from A,B;
2)内连接查询(使用的关键字inner join -- inner可以省略)
隐式内连接(SQL92标准): select * from A,B where条件;
显示内连接(SQL99标准): select * from A inner join B on条件;
3)外连接查询(使用的关键字outer join -- outer可以省略)
左外连接: left outer join
select * from A left outer join B on条件;
右外连接: right outer join
select * from A right outer join B on条件;
满外连接: full outer join
select* from A full outer join B on条件;
4)子查询
select的嵌套
5)表自关联:
将一张表当成多张表来用
交叉连接查询返回被连接的两个表所有数据行的笛卡尔积
笛卡尔积可以理解为一张表的每一行去和另外一张表的任意一行进行匹配
假如A表有m行数据,B表有n行数据,则返回m*n行数据
笛卡尔积会产生很多冗余的数据,后期的其他查询可以在该集合的基础上进行条件筛选
格式:
select * from 表1,表2,表3...;
select * from dept3,emp3;
内连接查询求多张表的交集
隐式内连接(SQL92标准): select * from A,B where条件;
显示内连接(SQL99标准): select * from A inner join B on条件;
--查询每个部门的所属员工
--隐式
select * from dept3,emp3 where deptno=dept_id;
select * from dept3,emp3 where dept3.deptno=emp3.dept_id;
select * from dept3 a,emp3 b where a.deptno=b.dept_id;
--显式
select * from dept3 inner join emp3 on deptno=dept_id;
select * from dept3 inner join emp3 on dept3.deptno=emp3.dept_id;
select * from dept3 a inner join emp3 b on a.deptno=b.dept_id;
--查询研发部和销售部的员工
select * from dept3 a join emp3 b on a.deptno=b.dept_id and (name='研发部' or name ='销售部');
select * from dept3 a join emp3 b on a.deptno=b.dept_id and name in('研发部','销售部');
--查询每个部门的员工,并升序
select a.deptno,count(1) from dept3 a join emp3 b on a.deptno=b.dept_id GROUP BY a.deptno;