我的编程空间,编程开发者的网络收藏夹
学习永远不晚

MySQL笔记-多表查询

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

MySQL笔记-多表查询

本文标签 : 多表查询  事务四大特性  并发事务问题  事务隔离级别

文章目录

目录

文章目录

一、多表查询

1.多表关系

2.多表查询概念

 3.多表查询的分类

 4.内连接

 5.外连接

6.自连接

 7.联合查询

 8.子查询  

1.标量子查询

2.列子查询

3.行子查询

4.表子查询

 9.多表查询案例练习

二、事务

1.事务简介

 2.事务操作 

 3.事务四大特性

4.并发事务引发的问题

 5.事务隔离级别,解决事务并发问题

总结


一、多表查询

1.多表关系

  • 概述:

  • 一对多(多对一): 

  • 多对多:   

演示:

-- -------------------------------- 多表关系 演示 ----------------------------------------------- 多对多 ----------------create table student(    id int auto_increment primary key comment '主键ID',    name varchar(10) comment '姓名',    no varchar(10) comment '学号') comment '学生表';insert into student values (null, '黛绮丝', '2000100101'),(null, '谢逊', '2000100102'),(null, '殷天正', '2000100103'),(null, '韦一笑', '2000100104');create table course(    id int auto_increment primary key comment '主键ID',    name varchar(10) comment '课程名称') comment '课程表';insert into course values (null, 'Java'), (null, 'PHP'), (null , 'MySQL') , (null, 'Hadoop');create table student_course(    id int auto_increment comment '主键' primary key,    studentid int not null comment '学生ID',    courseid  int not null comment '课程ID',    constraint fk_courseid foreign key (courseid) references course (id),    constraint fk_studentid foreign key (studentid) references student (id))comment '学生课程中间表';insert into student_course values (null,1,1),(null,1,2),(null,1,3),(null,2,2),(null,2,3),(null,3,4);

student_course : 

student :

course :

 

关系视图 : 

 

  •  一对一 :

演示: 

-- --------------------------------- 一对一 ---------------------------create table tb_user(    id int auto_increment primary key comment '主键ID',    name varchar(10) comment '姓名',    age int comment '年龄',    gender char(1) comment '1: 男 , 2: 女',    phone char(11) comment '手机号') comment '用户基本信息表';create table tb_user_edu(    id int auto_increment primary key comment '主键ID',    degree varchar(20) comment '学历',    major varchar(50) comment '专业',    primaryschool varchar(50) comment '小学',    middleschool varchar(50) comment '中学',    university varchar(50) comment '大学',    userid int unique comment '用户ID',    constraint fk_userid foreign key (userid) references tb_user(id)) comment '用户教育信息表';insert into tb_user(id, name, age, gender, phone) values        (null,'黄渤',45,'1','18800001111'),        (null,'冰冰',35,'2','18800002222'),        (null,'码云',55,'1','18800008888'),        (null,'李彦宏',50,'1','18800009999');insert into tb_user_edu(id, degree, major, primaryschool, middleschool, university, userid) values        (null,'本科','舞蹈','静安区第一小学','静安区第一中学','北京舞蹈学院',1),        (null,'硕士','表演','朝阳区第一小学','朝阳区第一中学','北京电影学院',2),        (null,'本科','英语','杭州市第一小学','杭州市第一中学','杭州师范大学',3),        (null,'本科','应用数学','阳泉第一小学','阳泉区第一中学','清华大学',4);

tb_user :

tb_user_edu :


2.多表查询概念

-- ------------------------------------> 多表查询 <---------------------------------------------- 准备数据create table dept(    id   int auto_increment comment 'ID' primary key,    name varchar(50) not null comment '部门名称')comment '部门表';create table emp(    id  int auto_increment comment 'ID' primary key,    name varchar(50) not null comment '姓名',    age  int comment '年龄',    job varchar(20) comment '职位',    salary int comment '薪资',    entrydate date comment '入职时间',    managerid int comment '直属领导ID',    dept_id int comment '部门ID')comment '员工表';-- 添加外键alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id);INSERT INTO dept (id, name) VALUES (1, '研发部'), (2, '市场部'),(3, '财务部'), (4, '销售部'), (5, '总经办'), (6, '人事部');INSERT INTO emp (id, name, age, job,salary, entrydate, managerid, dept_id) VALUES            (1, '金庸', 66, '总裁',20000, '2000-01-01', null,5),            (2, '张无忌', 20, '项目经理',12500, '2005-12-05', 1,1),            (3, '杨逍', 33, '开发', 8400,'2000-11-03', 2,1),            (4, '韦一笑', 48, '开发',11000, '2002-02-05', 2,1),            (5, '常遇春', 43, '开发',10500, '2004-09-07', 3,1),            (6, '小昭', 19, '程序员鼓励师',6600, '2004-10-12', 2,1),            (7, '灭绝', 60, '财务总监',8500, '2002-09-12', 1,3),            (8, '周芷若', 19, '会计',48000, '2006-06-02', 7,3),            (9, '丁敏君', 23, '出纳',5250, '2009-05-13', 7,3),            (10, '赵敏', 20, '市场部总监',12500, '2004-10-12', 1,2),            (11, '鹿杖客', 56, '职员',3750, '2006-10-03', 10,2),            (12, '鹤笔翁', 19, '职员',3750, '2007-05-09', 10,2),            (13, '方东白', 19, '职员',5500, '2009-02-12', 10,2),            (14, '张三丰', 88, '销售总监',14000, '2004-10-12', 1,4),            (15, '俞莲舟', 38, '销售',4600, '2004-10-12', 14,4),            (16, '宋远桥', 40, '销售',4600, '2004-10-12', 14,4),            (17, '陈友谅', 42, null,2000, '2011-10-12', 1,null);

查询两张表的数据     直接查询的结果:  可以看到有大量的无效的数据

要想从 emp 表和 dept 表中查询数据 ,要先对无效的笛卡尔积进行消除 :

-- 多表查询 -- 笛卡尔积select * from emp , dept where emp.dept_id = dept.id;

清除后 : 

  


 3.多表查询的分类


 4.内连接

演示  

-- 内连接演示-- 1. 查询每一个员工的姓名 , 及关联的部门的名称 (隐式内连接实现)-- 表结构: emp , dept-- 连接条件: emp.dept_id = dept.idselect emp.name , dept.name from emp , dept where emp.dept_id = dept.id ;# 给表起别名,不能再通过表名来限定字段select e.name,d.name from emp e , dept d where e.dept_id = d.id;-- 2. 查询每一个员工的姓名 , 及关联的部门的名称 (显式内连接实现)  --- INNER JOIN ... ON ... (inner 可以省略)-- 表结构: emp , dept-- 连接条件: emp.dept_id = dept.idselect e.name, d.name from emp e inner join dept d  on e.dept_id = d.id;select e.name, d.name from emp e join dept d  on e.dept_id = d.id;

结果 : 


 5.外连接

演示 : 

-- 外连接演示-- 1. 查询emp表的所有数据, 和对应的部门信息(左外连接) (会完全的显示左表内容以及和右表交集的查询内容)-- 表结构: emp, dept-- 连接条件: emp.dept_id = dept.idselect e.*,d.name from emp e left outer join dept d on e.dept_id = d.id;select e.*, d.name from emp e left join dept d on e.dept_id = d.id;-- 2. 查询dept表的所有数据, 和对应的员工信息(右外连接) (会完全的显示右表内容以及和左表交集的查询内容)select d.*, e.* from emp e right outer join dept d on e.dept_id = d.id;# 如果改成左外连接,只需调换一下左右表的顺序即可select d.*, e.* from dept d left outer join emp e on e.dept_id = d.id;

结果 : 

 


6.自连接

演示 :

自连接可以将自身看成两张表 a 和 b ,a 表 和 b 表 的连接条件是 

    a表的 managerid = b表的 id

演示 : 

-- 自连接-- 1. 查询员工 及其 所属领导的名字-- 表结构: emp  (必须起别名 可以理解为使用内连接查询表交集部分的数据)select a.name,b.name from emp a , emp b where a.managerid = b.id;-- 2. 查询所有员工 emp 及其领导的名字 emp , 如果员工没有领导, 也需要查询出来-- 表结构: emp a , emp b  (没有领导也要查询出来,可以理解为使用外连接查询完整的表)select a.name '员工',b.name '领导' from emp a left outer join emp b on a.managerid = b.id;

结果 : 


 7.联合查询

演示 : 

-- union all , union-- 1. 将薪资低于 5000 的员工 , 和 年龄大于 50 岁的员工全部查询出来.-- 直接将查询的两个结果合并select * from emp where salary < 5000union allselect * from emp where age > 50;-- 去除重复数据 可以删去关键字 allselect * from emp where salary < 5000unionselect * from emp where age > 50;

注意 : 联合查询的多张表的列数必须保持一致 ,字段类型也要保持一致.

结果 :


 8.子查询  

1.标量子查询

演示 : 

-- -------------------------------------- 子查询 -------------------------- 标量子查询-- 1. 查询 "销售部" 的所有员工信息-- 第一步. 查询 "销售部" 部门IDselect id from dept where name = '销售部';-- 第二步. 查询部门 id 为 4 查询员工信息select * from emp where dept_id = 4;-- 第三步. 合并select * from emp where dept_id = (select id from dept where name = '销售部');-- 2. 查询在 "方东白" 入职之后的员工信息-- 第一步. 查询 方东白 的入职日期select entrydate from emp where name= '方东白';-- 第二步. 查询他之后的员工信息select * from emp where entrydate > '2009-02-12';-- 第三步. 合并select * from emp where entrydate > (select entrydate from emp where name= '方东白');

结果 :

2.列子查询

演示 : 

-- 列子查询-- 1. 查询 "销售部" 和 "市场部" 的所有员工信息-- a. 查询 "销售部" 和 "市场部" 的部门IDselect id from dept where name = '销售部' or name = '市场部';-- b. 根据部门ID, 查询员工信息 ( in: 在指定范围内查找 )select * from emp where dept_id in (2,4);-- c. 合并select * from emp where dept_id in (select id from dept where name = '销售部' or name = '市场部');-- 2. 查询比 财务部 所有人工资都高的员工信息-- a. 查询所有 财务部 人员工资select id from dept where name = '财务部';select salary from emp where dept_id = (select id from dept where name = '财务部');-- b. 比 财务部 所有人工资都高的员工信息 (高于财务部最高工资的人, all : 查询返回的列表都需要满足条件)select * from emp where salary > all (select salary from emp where dept_id = (select id from dept where name = '财务部'));-- 3. 查询比研发部其中任意一人工资高的员工信息-- a. 查询研发部所有人工资select id from dept where name = '研发部';select salary from emp where dept_id = (select id from dept where name = '研发部');-- b. 比研发部其中任意一人工资高的员工信息 ( any/some : 查询满足其中的任意一个条件)select * from emp where salary > any (select salary from emp where dept_id = (select id from dept where name = '研发部'));

结果 :

 

3.行子查询

演示 : 

-- 行子查询-- 1. 查询与 "张无忌" 的薪资及直属领导相同的员工信息 ;-- a. 查询 "张无忌" 的薪资及直属领导select salary,managerid from emp where name = '张无忌';-- b. 查询与 "张无忌" 的薪资及直属领导相同的员工信息 ;select * from emp where (salary,managerid) = (select salary,managerid from emp where name = '张无忌');

结果 : 

4.表子查询

演示 :

-- 表子查询-- 1. 查询与 "鹿杖客" , "宋远桥" 的职位和薪资相同的员工信息-- a. 查询 "鹿杖客" , "宋远桥" 的职位和薪资select job,salary from emp where name='鹿杖客' or name='宋远桥';-- b. 查询与 "鹿杖客" , "宋远桥" 的职位和薪资相同的员工信息select * from emp where (job,salary) in (select job,salary from emp where name='鹿杖客' or name='宋远桥');-- 2. 查询入职日期是 "2006-01-01" 之后的员工信息 , 及其部门信息-- a. 入职日期是 "2006-01-01" 之后的员工信息select * from emp where entrydate > '2006-01-01';-- b. 查询这部分员工, 对应的部门信息;select e.*,d.* from (select * from emp where entrydate > '2006-01-01') e left join dept d on e.dept_id = d.id;

结果 :

 


 9.多表查询案例练习

演示 :

-- ---------------------------------------> 多表查询案例 <----------------------------------create table salgrade(    grade int,    losal int,    hisal int) comment '薪资等级表';insert into salgrade values (1,0,3000);insert into salgrade values (2,3001,5000);insert into salgrade values (3,5001,8000);insert into salgrade values (4,8001,10000);insert into salgrade values (5,10001,15000);insert into salgrade values (6,15001,20000);insert into salgrade values (7,20001,25000);insert into salgrade values (8,25001,30000);-- 1. 查询员工的姓名、年龄、职位、部门信息 (隐式内连接)-- 表: emp , dept-- 连接条件: emp.dept_id = dept.idselect e.name , e.age , e.job , d.name from emp e,dept d where e.dept_id = d.id;-- 2. 查询年龄小于30岁的员工的姓名、年龄、职位、部门信息(显式内连接)-- 表: emp , dept-- 连接条件: emp.dept_id = dept.idselect e.name , e.age , e.job , d.name from emp e join dept d on e.dept_id = d.id where age < 30;-- 3. 查询 拥有 员工的部门ID、部门名称 (人事部没有员工)-- 表: emp , dept-- 连接条件: emp.dept_id = dept.id  distinct关键字去重select distinct d.id , d.name from emp e,dept d where e.dept_id = d.id;-- 4. 查询所有年龄大于40岁的员工, 及其归属的部门名称; 如果员工没有分配部门, 也需要展示出来-- 表: emp , dept-- 连接条件: emp.dept_id = dept.id-- 外连接select e.* , d.name from emp e left join dept d on d.id = e.dept_id where age > 40;-- 5. 查询所有员工的工资等级-- 表: emp , salgrade-- 连接条件 : emp.salary >= salgrade.losal and emp.salary <= salgrade.hisalselect e.* , s.grade , s.losal , s.hisal  from emp e , salgrade s where e.salary >= s.losal and e.salary <= s.hisal;-- between...and 写法select e.* , s.grade , s.losal, s.hisal from emp e , salgrade s where e.salary between s.losal and s.hisal;-- 6. 查询 "研发部" 所有员工的信息及 工资等级-- 表: emp , salgrade , dept-- 连接条件 : emp.salary between salgrade.losal and salgrade.hisal , emp.dept_id = dept.id-- 查询条件 : dept.name = '研发部'select e.*, s.gradefrom emp e,     dept d,     salgrade swhere e.dept_id = d.id  and (e.salary between s.losal and s.hisal)  and d.name = '研发部';-- 7. 查询 "研发部" 员工的平均工资-- 表: emp , dept-- 连接条件 :  emp.dept_id = dept.idselect avg(e.salary) from emp e , dept d where e.dept_id = d.id and d.name = '研发部';-- 8. 查询工资比 "灭绝" 高的员工信息。-- a. 查询 "灭绝" 的薪资select salary from emp where name = '灭绝';-- b. 查询比她工资高的员工数据select * from emp where salary > (select salary from emp where name = '灭绝');-- 9. 查询比平均薪资高的员工信息-- a. 查询员工的平均薪资select avg(salary) from emp;-- b. 查询比平均薪资高的员工信息select * from emp where salary > (select avg(salary) from emp);-- 10. 查询低于本部门平均工资的员工信息-- a. 查询指定部门平均薪资  1select avg(e1.salary) from emp e1 where dept_id = 1;select avg(e1.salary) from emp e1 where dept_id = 2;-- b. 查询低于本部门平均工资的员工信息select *, (select avg(e1.salary) from emp e1 where dept_id = e2.dept_id) '平均'from emp e2where salary < (select avg(e1.salary) from emp e1 where dept_id = e2.dept_id);-- 11. 查询所有的部门信息, 并统计部门的员工人数select d.id , d.name , (select COUNT(*) from emp e where e.dept_id = d.id) '人数' from dept d;select COUNT(*) from emp where dept_id = 1;-- 12. 查询所有学生的选课情况, 展示出学生名称, 学号, 课程名称-- 表: student , course , student_course-- 连接条件: student.id = student_course.studentid , course.id = student_course.courseidselect s.name, s.no, c.namefrom student s,     student_course sc,     course cwhere s.id = sc.studentid  and sc.courseid = c.id;

二、事务

1.事务简介


 2.事务操作 

操作方法 1 :

操作方法 2 :

 提交事务执行使用 commit ,如果执行过程中发生错误, 则 返回初始值 rollback.

 演示 :

-- ---------------------------- 事务操作 ------------------------------ 数据准备create table account(    id int auto_increment primary key comment '主键ID',    name varchar(10) comment '姓名',    money int comment '余额') comment '账户表';insert into account(id, name, money) VALUES (null,'张三',2000),(null,'李四',2000);-- 恢复数据update account set money = 2000 where name = '张三' or name = '李四';select @@autocommit; -- 查询当前事务执行方式, 查询结果 0 为手动提交 , 1 为自动提交set @@autocommit = 0; -- 设置为手动提交-- 转账操作 (张三给李四转账1000)-- 1. 查询张三账户余额select * from account where name = '张三';-- 2. 将张三账户余额-1000update account set money = money - 1000 where name = '张三';程序执行报错 ... -- 这里程序执行错误,前面两条语句执行,下面语句不会执行-- 3. 将李四账户余额+1000update account set money = money + 1000 where name = '李四';-- 事务执行成功,没有错误则 提交事务 手动提交commit;-- 回滚事务 如果执行过程出错,则执行回滚操作,返回初始值rollback ;-- 方式二-- 转账操作 (张三给李四转账1000)start transaction ;  -- 开启事务-- 1. 查询张三账户余额select * from account where name = '张三';-- 2. 将张三账户余额-1000update account set money = money - 1000 where name = '张三';程序执行报错 ... -- 这里程序执行错误,前面两条语句执行,下面语句不会执行-- 3. 将李四账户余额+1000update account set money = money + 1000 where name = '李四';-- 事务执行成功,没有错误则 提交事务 手动提交commit;-- 回滚事务 如果执行过程出错,则执行回滚操作,返回初始值rollback;

 3.事务四大特性

  •  原子性 : 要么事务执行成功要么就执行失败,进行回滚操作再进行下一次提交事务.
  •  一致性 : 比如例子中的转账操作,事务提交无论成功或失败,张三和李四账户的余额加起来是一个恒定的值,不会发生增加或减少.
  • 比如两个事务 A 和 B ,两个事务在操作过程中彼此之间不会影响之间的执行,两个事务是在独立的环境下运行.
  • 事务不管是操作成功提交了还是操作失败回滚了,它对数据库当中的数据改变是永久的,数据库当中的数据最终是存储在磁盘当中,所有数据就会永久的保留下来.

4.并发事务引发的问题

并发事务引起的问题 :多个并发执行事务在操作同一个数据库/表所引起的问题.

  • 脏读(没有执行完的事务 A 存储到磁盘后被事务 B 读取,则为脏读 ) : MySQL的隔离级别默认可以重复读取,也就是说未提交的数据根本读不到,这里只是告诉我们会有这种情况发生,而数据库隔离级别不会不会产生这种情况.
  •  不可重复读 : 事务 A 第一次执行查询一个 id=1 的语句后,再令 事务 B 更新了刚刚查询的语句 id=1 并且提交 ,如果 事务 A 再执行相同的查询 id=1 我们发现,此时查询出来的数据和第一次查询出来的数据不一样,这个现象就称为不可重复读.
  • 幻读(解决了不可重复读后引发出来的) : 

 5.事务隔离级别,解决事务并发问题

read uncommintted : (会出现脏读) 

如果相反设置为 set session transaction isolation level read committed;后再次执行上面的操作,如果不进行 commit; 提交则数据不会发生改变.

read commintted : (会出现不可重复提交问题)

如果设置为 set session transaction isolation level repeatable read; 后再次 commit 提交,不可重复读问题就会被解决.

 repeatable read : (会出现幻读问题)

 要想解决幻读问题,则要设置事务的隔离级别为 set session transaction isolation level serializable;

 serializable (可以规避所有的并发事务问题,但是它的性能是最差的) : A 事务 commit 提交后, B 事务才能进行操作. 

注意 : 事务的隔离级别越高, 数据越安全, 但是性能越低 .


总结

多表查询 :

事务 :


码文不易,三联支持一下呗

如有不足,还望指出.

来源地址:https://blog.csdn.net/2201_75533641/article/details/130543935

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

MySQL笔记-多表查询

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

学习笔记:MYSQL查询

前言:之前花费两天晚上看了一遍Mysql必知必会,没想到后面效果太差。不如跟着网课视频敲一遍和完成练习题目(练习题没写注释就不记录了),再记下笔记。一、基本的查询select语句语法: select 查询列表 from 表名;查询列表可以是表中的字段、常量值、
学习笔记:MYSQL查询
2015-12-27

MySQL之单表查询、多表查询

一、单表查询:单个表的查询方法及语法顺序需要通过实际例子来熟悉先将表数据创建下:mysql> create database singe_t1; # 建个数据库singe_t1Query OK, 1 row affected (0.01
2023-01-31

MySQL 多表查询

union 结果集合并使用多个select分别查询不同的表,把多个select查到的记录合并在一起一个select查到m条记录,另一个select查到n条记录,合并之后就是m+n条记录 #查询全校师生的id、name,使用2个select分别从tb_teach
MySQL  多表查询
2017-05-29

mysql-多表查询

准备工作:准备两张表,部门表(department)、员工表(employee)mysql> create database db2;Query OK, 1 row affected (0.00 sec)mysql> use db2;Dat
2023-01-30

MySQL----多表查询

MySQL----多表查询 多表关系表与表之间的联系:一对多(多对一)多对多一对一 多表查询多表查询的分类数据准备内连接外连接自连接联合查询子查询标量子查询列子查询行子查询表子查询 多表查询案例 多表关系 在进
2023-08-19

【MySQL】MySQL表之联合查询(多表查询)

📌前言:本篇博客介绍MySQL数据库的MySQL表之联合查询(多表查询),学习MySQL之前要先安装好MySQL,如果还没有安装的小伙伴可以看看博主前面的博客,里面有详细的安装教程。 那我们废话不多说,直接进入主体!
2023-08-16

连接查询(多表查询)——MySQL

连接查询(多表查询) 又称多表查询,当查询的字段涉及多个表的时候,就要用到连接查询 分类: 为表起别名: 提高语句的简洁度区分多个重名字段注意:如果为表起了别名,则查询的字段就不能使用原来的别名去限定 内连接 查询A、B 交集部分数据 语
2023-08-18

Mysql 多表关联查询

文章目录 1. Mysql中表之间的关系1.1 多表关系1.2 外键约束 2. 多表联合查询2.1 交叉连接查询:笛卡尔积2.2 内连接查询:inner join2.3 外连接查询2.3.1 左连接:2.3.2 右连接:2.3.
2023-08-21

详解MySQL多表查询

目录多表查询内连接查询外连接查询子查询最后说一句多表查询内连接查询语法-- 隐式内连接SELECT 字段列表 FROM 表1,表2… WHERE 条件;-- 显示内连接SELEsPIFtHEZBxCT 字段列表 FROM 表1 p
2023-04-19

编程热搜

目录