个人主页:Nezuko627的博客主页
❤️ 支持我: 点赞 收藏 关注
格言:一步一个脚印才能承接所谓的幸运本文来自专栏:MySQL8.0学习笔记
本文参考视频:MySQL数据库全套教程
欢迎点击支持订阅专栏 ❤️
一对一关系
一对多/多对一关系
多对多关系
简介:
MySQL 外键约束是表的一种特殊字段,经常与主键约束一起使用。对于两个具有关联关系的表而言,相关联字段中主键所在的表就是主表(父表),外键所在的表就是从表(子表)。
外键约束用来建立主表与从表的关联关系,为两个表的数据建立连接,约束两个表中数据的一致性和完整性。
举例说明:
在下图中,从表中的部门号受主表中的主键部门号的范围限制, 即,从表中的部门号列只能取值为1001、1002或1003。
定义外键的规则:
1.在创建表时设置外键约束
在 create table
语句中,使用 foreign key
关键字来指定外键。具体语法格式如下:
[constraint <外键名>] foreign key 字段名1 [, 字段名2, ...]
references <主表名> 主键列1, [, 主键列2, ...]
2.修改表时添加外键约束
这样做的前提是:从表中外键的列中的数据必须与主键中主键列中的数据一致或没有数据。 语法如下:
alter table <数据表名>
add constraint <外键名> foreign key(<列名>)
references <主表名> (<列名>);
下面使用下面这段代码创建两个表,dept 作主表存储部门信息,emp 作从表存储员工信息,主键约束与外键约束详细见代码注释:
-- 创建部门表(主表)
CREATE TABLE IF NOT EXISTS dept
(
deptno 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 (deptno) -- 外键约束
)
结果: 外键约束创建成功,图示表明 emp
表的 eid
受到主表 dept
的主键 deptno
外键约束。
下面我们给已经创建好的两个表添加数据,用于 验证外键约束的作用, 相关代码如下图:
因此我们将最后一条更正为 ‘1004’,更正后的代码如下:
-- 1. 添加主表数据
INSERT INTO dept
VALUES ('1001', '研发部'),
('1002', '销售部'),
('1003', '财务部'),
('1004', '人事部');
-- 2. 添加从表数据
INSERT INTO emp
VALUES ('1', 'Nezuko627', 20, '1001'),
('2', 'Whisper', 19, '1001'),
('3', '大头呢', 21, '1001'),
('4', '小牛马', 21, '1002'),
('5', '小鹏', 25, '1002'),
('6', '几何心凉', 25, '1002'),
('7', '草帽路飞', 17, '1003'),
('8', '娜美', 16, '1003'),
('9', '乔巴', 5, '1004');
在表中删除数据:
当一个表中不需要外键约束时,就需要从表中删除。外键一旦删除,就会解除和主表的关联关系
语法格式:
alter table <表名> drop foreign key <外键约束名>;
多对多关系相对来说更加复杂,简单的来说,就是需要:使用一张中间表作为从表来关联其余的主表。 如下图所示:
下面我们根据图示来创建这三个表,并添加相应的外键约束,相关代码如下:
-- 1. 创建主表1 学生表 student
CREATE TABLE IF NOT EXISTS student
(
sid INT PRIMARY KEY AUTO_INCREMENT, -- 学号
name VARCHAR(20), -- 姓名
age INT -- 年龄
);
-- 2. 创建主表2 课程表 course
CREATE TABLE IF NOT EXISTS course
(
cid INT PRIMARY KEY, -- 课程号
cname VARCHAR(20) -- 课程名
);
-- 3. 创建中间表 额外添加一个成绩
CREATE TABLE IF NOT EXISTS score
(
sid INT, -- 学号
cid INT, -- 课程号
score DOUBLE -- 成绩
);
-- 4. 添加外键约束
ALTER TABLE score
ADD FOREIGN KEY (sid) REFERENCES student (sid);
ALTER TABLE score
ADD FOREIGN KEY (cid) REFERENCES course (cid);
-- 5. 添加数据
INSERT INTO student
VALUES (1, 'Whisper', 18),
(2, '大头呢', 19),
(3, 'Nezuko', 20);
INSERT INTO course
VALUES (1, '程序设计'),
(2, '大学英语'),
(3, '高等数学');
INSERT INTO score
VALUES (1, 1, 98),
(2, 2, 86),
(2, 1, 95),
(2, 3, 75),
(3, 2, 99),
(3, 3, 76);
结果:
在表中删除数据: 中间从表可以随便删除和修改,但是两边的主表受从表依赖的数据不能删除或修改。
简介:
多表查询就是同时查询两个或两个以上的表,主要用于展示一对多、多对多的数据,需要展示的数据来自于多张表。
分类概述:
接下来准备多表查询需要的数据。需要注意的是, 外键约束只影响增删,对多表查询并无影响! 数据准备代码如下:
-- 创建部门表
CREATE TABLE IF NOT EXISTS dept
(
deptno 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) -- 部门号
)
-- 给部门表添加数据
INSERT INTO dept VALUES ('1001', '研发部');
INSERT INTO dept VALUES ('1002', '销售部');
INSERT INTO dept VALUES ('1003', '财务部');
INSERT INTO dept VALUES ('1004', '人事部');
-- 给员工表添加数据
INSERT INTO emp VALUES ('1', '乔巴', 20, '1001');
INSERT INTO emp VALUES ('2', '路飞', 21, '1001');
INSERT INTO emp VALUES ('3', '祢豆子', 23, '1001');
INSERT INTO emp VALUES ('4', '漩涡鸣人', 18, '1001');
INSERT INTO emp VALUES ('5', '春野樱', 85, '1002');
INSERT INTO emp VALUES ('6', '洛克李', 33, '1002');
INSERT INTO emp VALUES ('7', '皮卡丘', 50, '1002');
INSERT INTO emp VALUES ('8', '胖丁', 60, '1003');
INSERT INTO emp VALUES ('9', '喵喵', 58, '1003');
INSERT INTO emp VALUES ('10', '淼淼', 3, '1005');
数据表如下:
简介:
语法:
select * from 表1, 表2, 表3...;
实现:
SELECT * FROM emp, dept;
-- 隐式内连接(SQL92标准)
select * from A, B where 条件;
-- 显式内连接(SQL99标准)
select * from A inner join B on 条件;
实现:
-- 隐式内连接方式
SELECT * FROM dept, emp WHERE dept.deptno = emp.dept_id;
-- 显示内连接方式
SELECT * FROM dept INNER JOIN emp ON dept.deptno = emp.dept_id;
-- 隐式内连接方式
SELECT * FROM dept, emp WHERE dept.deptno = emp.dept_id AND dept.name = '研发部';
-- 显示内连接方式
SELECT * FROM dept INNER JOIN emp ON dept.deptno = emp.dept_id AND dept.name = '研发部';
-- 隐式内连接方式
SELECT dept.name, count(*) 'count'
FROM dept,
emp
WHERE dept.deptno = emp.dept_id
GROUP BY dept.deptno
ORDER BY count ASC;
-- 显示内连接式
SELECT dept.name, count(*) 'count'
FROM dept
INNER JOIN emp ON dept.deptno = emp.dept_id
GROUP BY dept.deptno
ORDER BY count ASC;
-- 隐式内连接方式
SELECT dept.name, count(emp.eid) count
FROM dept,
emp
WHERE dept.deptno = emp.dept_id
GROUP BY dept.deptno
HAVING count >= 3
ORDER BY count DESC;
-- 显式内连接方式
SELECT dept.name, count(emp.eid) count
FROM dept
JOIN
emp
ON dept.deptno = emp.dept_id
GROUP BY dept.deptno
HAVING count >= 3
ORDER BY count DESC;
外连接分为左外连接
、右外连接
、满外连接
。需要注意的是,在Oracle中有 full join,但是在 mysql 中对 full join 支持不友好,可以使用 union 来达到目的。
通俗说,在mysql中满外连接可以通过求左外连接与右外连接的并集实现。
来看几个例子吧:
1️⃣ 查询哪些部门有员工,哪些部门没有员工
SELECT * FROM dept LEFT OUTER JOIN emp ON dept.deptno = emp.dept_id;
2️⃣ 查询哪些员工有对应的部门,哪些没有
SELECT * FROM dept RIGHT OUTER JOIN emp ON dept.deptno = emp.dept_id;
3️⃣ 利用 union
关键字实现求左外连接和右外连接的并集
SELECT *
FROM dept
LEFT OUTER JOIN emp ON dept.deptno = emp.dept_id
UNION
SELECT *
FROM dept
RIGHT OUTER JOIN emp ON dept.deptno = emp.dept_id;
简介:
子查询就是 在一个完整的查询语句中,嵌套若干个不同功能的小查询, 从而一起完成复杂的查询的一种编写方式
子查询的返回结果分为如下四种:
1️⃣ 查询年龄最大的员工信息,显示该员工的员工号、员工名字和年龄
SELECT eid, ename, age
FROM emp
WHERE age = (SELECT max(age) FROM emp);
2️⃣ 查询研发部和销售部的员工信息,包含员工号、姓名
SELECT eid, ename
FROM dept
JOIN emp ON dept.deptno = emp.dept_id AND (name in ('销售部', '研发部'));
SELECT eid, ename
FROM emp
WHERE dept_id IN (SELECT deptno FROM dept WHERE name IN ('销售部', '研发部'));
3️⃣ 查询研发部30岁以下员工的所有信息(指员工表)
SELECT *
FROM dept
JOIN emp ON dept.deptno = emp.dept_id AND (dept.name = '研发部' AND emp.age < 30);
SELECT *
FROM (SELECT *
FROM dept
WHERE name = '研发部') T1
JOIN (SELECT *
FROM emp
WHERE age < 30) T2 ON T1.deptno = T2.dept_id;
语法格式:
SELECT ... FROM ... WHERE c > ALL(查询语句);
说明:
⭕️ 操作:
查询年龄大于 1003 部门所有员工的员工信息
SELECT *
FROM emp
WHERE age > ALL (SELECT age FROM emp WHERE dept_id = '1003');
语法格式:
SELECT ... FROM ... WHERE c > ANY(查询语句);
说明:
⭕️ 操作:
查询年龄大于 1003 部门任一员工的员工信息
SELECT *
FROM emp
WHERE age > ANY (SELECT age FROM emp WHERE dept_id = '1003');
语法格式:
SELECT ... FROM ... WHERE c IN(查询语句);
说明:
⭕️ 操作:
查询研发部和销售部的员工信息
SELECT *
FROM emp
WHERE dept_id IN (SELECT deptno FROM dept WHERE name = '研发部' OR name = '销售部');
语法格式:
SELECT ... FROM ... WHERE EXISTS(查询语句);
说明:
Tips:EXISTS关键字运算效率比IN高,实际开发中更推荐使用。
⭕️ 操作:
查询公司是否有大于60岁的员工,有则输出
SELECT *
FROM emp
WHERE EXISTS (SELECT * FROM emp WHERE age > 60);
是不是困惑?为什么查询结果中有年龄小于60岁的呢? 其实 EXISTS 只是判断子查询中是否有返回数据,在查询中,判断出有大于60岁的员工,因此 外层查询实际上是查询了所有员工的信息。
我们可以 通过取别名的方式,一条一条取数据,让外查询来决定条件是否成立,来达到只取年龄大于60岁的员工信息。
简介:
MySQL有时在信息的查询时需要进行对表自身进行关联查询。即一张表和自己关联,将一张表当成多张表来使用。自相关查询时必须给表取别名。
语法:
-- 方式1
select 字段列表 from 表1 别名1, 表1 别名2 where 条件;
-- 方式2
select 字段列表 from 表1 别名1 [left] join 表1 别名2 on 条件;
使用场景举例:
比如员工表,员工中既有老板又有普通员工,这时候就可以通过自关联查询的方式,将员工表分成多个来进行关联查询,查询员工的老板是谁… …
以上便是本文的全部内容啦,后续内容将会持续免费更新,如果文章对你有所帮助,麻烦动动小手点个赞 + 关注,非常感谢 ❤️ ❤️ ❤️ !
如果有问题,欢迎私信或者评论区!
共勉:“你间歇性的努力和蒙混过日子,都是对之前努力的清零。”