MYSQL学习之子查询(表连接查询)以及权限控制

版权声明:本文为博主原创文章,未经博主允许不得转载。https://blog.csdn.net/qq_37757008/article/details/81408567 https://blog.csdn.net/qq_37757008/article/details/85239316

在上一篇博客里我们详细的介绍了MySQL语言的DDL(数据定义语言) 和 DML(数据操作语言),那么在这篇博客中我们要对上次的DML进行补充;同时我们要介绍DCL(数据控制语言);

子查询

在学习子查询的开始我们由这样一个问题来引出;
我们现在有一张员工表emp,该表中包含员工的编号,姓名,薪资,入职日期等等信息;
假如我们现在想在这张表中查询最高薪资员工的员工信息,那按照我们之前学的知识来说,我们可能会这么写:

select max(sal),e.* from emp e;

乍一看这么写没什么错,我们获得最高工资和最高工资的人的所有信息,可是实际上它是有问题的,会报错;我们想一下,如果我们的表中有两个人同时有着最高的工资,那我们按照上面的语句查询就会发现我们获得的最高工资是一行,而对应的人信息却需要输出两行;这显然是不行的;这时候我们就需要用到子查询了;

  • 子查询定义:
    子查询允许把一个查询嵌套在另一个查询当中。
    子查询,又叫内部查询,相对于内部查询,包含内部查询的就称为外部查询。
    子查询可以包含普通select可以包括的任何子句,比如:distinct、 group by、order by、limit、join和union等;但是对应的外部查询必须是以下语句之一:select、insert、update、delete、set或 者do。
    说的通俗一点,子查询就是把一个查询语句的结果当作另一个查询语句的条件;

  • 子查询的分类
    根据子查询返回值的数量,将子查询可以分为标量子查询和多值子查询。

  1. 标量子查询:返回单一值的标量,最简单的形式。
    也就是将子查询的结果当作一个值
  2. 表子查询:返回的结果集是 N 行 N 列
    也就是将子查询的结果当作一张表

标量子查询

这时候我们再看上面的问题,用了子查询我们就可以这么做:
首先我们要获得表中的最高工资是多少;

select max(sal) from emp;

在这里插入图片描述
这句话获得了表中的最高工资,我们看到是5000;
那现在我们想获得工资是5000的人都有谁:

select * from emp where sal = 5000;

在这里插入图片描述
我们发现我们第一个语句查到的5000 就是第二个语句的检索条件,那我们把第二句中的5000换成上面的语句,把这两句语句合并起来,一句就查出最高工资的人:

select * from emp where sal = (select max(sal) from emp);

在这里插入图片描述

表子查询

同样我们也用一个问题来引出;
比如我们想查询每个部门的最高工资的员工;那这个我们该怎么做呢?
首先我们肯定要对部门进行分组获得不同部门的最大工资和部门编号;

select max(sal) maxsal,deptno from emp group by deptno; 

我们按照部门编号进行分组,获得同部门中的最高工资给这个列一个临时名字叫maxsa,以及各部门对应的部门编号;
在这里插入图片描述

这时我们看到我们查询到的结果是一张表,我们不能向标量子查询一样,将它当作一个值来做条件了,而这时我们就应该想到上一篇博客中学到的表连接操作。我们将上面查询到的结果当作一张临时表a,然后和我们的员工表连接,选取两张表中工资和部门编号相同的人,将它的信息搜索出来,这样就达到了目的;

select * from emp b inner join 
(select max(sal) maxsal,deptno from emp group by deptno) a 
on b.sal = a.maxsal and b.deptno = a.deptno;

在这里插入图片描述
我们可以看到上面的结果就是我们想要的结果,不同部门中的最高工资的所有员工信息;当然我们上面是直接查询了两张表连接了之后的所有信息,其实表中的sal和maxsal以及后面的部门编号再前面的员工信息中都有,你也可以对它们进行规范化输出,只获取你想要的数据列;即不是select * ,而是select empno,ename,job… 让它输出特定的列;

以上我们用的所有子查询都是优化过后的子查询,我们可能看到这样的子查询写法:

SELECT * FROM emp WHERE (sal,deptno) IN (select max(sal) maxsal,deptno from emp group by deptno);

这样的子查询虽然也可以得到想要的数据,但其实它是不够高效的方法;我们可以看看结果:
在这里插入图片描述

我们可以发现查询同样的内容,上面的方式用时0.42秒,而下面用inner join 关键字的方法明显更加高效,更快,使用时间已经在毫秒级了,他们两种方法看起来异曲同工,实则用时早以不在同一个量级了;
那么这时什么原因呢?
  这是因为在子查询时,MySQL需要为内层查询语句的查询结果建立一个临时表。然后外层查询语句再临时表中查询记录。查询完毕 后,MySQL需要撤销这些临时表。因此,子查询的速度会受到一定的影响。如果查询的数据量比较大,这种影响就会随之增大。
  而我们上面所有使用的查询严格意义上已经不能叫子查询了,而是使用连接查 询来替代子查询。
  连接查询不需要建立临时表,其速度比子查询要快。


DCL(数据控制语言)

在这里我们介绍的数据控制语言其实就是对用户进行权限的控制操作;
grant (授权) 和 revoke(回收权限)

  1. 创建用户
create user 用户名 identified by '密码';

例如:
create user test identified by ‘12345’;

  1. 授权语法:
grant 权限 to 用户名;

例如:把查询test库中所有表的查询权限授权给test;
grant select on test.* to test;
这时我们登陆test账户看一下,由于我们只给了test用户查询test表的权限,所以我们甚至不能看到整个mysql 中有那些数据库;
在这里插入图片描述
同时我们也只能对数据库test进行查询操作,无法增删改;
在这里插入图片描述
INSERT command denied to user ‘test’@‘localhost’
就代表我们没有对这个表进行insert操作的权限;

  1. 回收权限
revoke 权限 from 用户名;

例如:回收之前分配的权限:
revoke select on test.* from test;

  1. 查看当前用户的权限
	select current_user();
	show grants for 用户名;

这两句配合使用,先查询用户名,然后查询到它的权限;


猜你喜欢

转载自blog.csdn.net/qq_37757008/article/details/85239316