MySQL概述及DQL

数据库就是用来存储数据的,之前的数据要么是直接存储在程序的变量中直接操作,要么是直接存储在文件中利用文件流来操作。但是呢,这些都不是存储数据的最佳方式,存储数据的最佳方式就是今天的重头戏:数据库啦!

废话不多说。

数据库有MySQL、Oracle,DB2,sql server等等,Java中最常用的就是MySQL,因为它轻量级,并且是开源的,最重要的是它免费,支持白嫖啊!

(MySQL是一个数据库管理系统,但是大家好像都习惯称为数据库了。)

先介绍一下DBMS,DB,SQL的区别:

  • DBMS:数据库管理系统。
  • DB:数据库。
  • SQL:结构化查询语言,一种标准的语法。

它们的关系是:DBMS通过执行SQL语句去操作DB中的数据。

再来看,什么是表?表是一种结构化的文件。用来存储数据

表就是有行有列吧,就和Excel中的一样。像下面这种:

学号 姓名 性别
001 Tom

不陌生吧,MySQL中的表也是一样的,有行有列:

  • 行,又称为记录(data);
  • 列,又称为字段(column)。

1.SQL语句的分类

SQL语句主要分为五大类:

  • DML数据操作语言:主要包含数据库中表数据的插入、删除、更新,即(insert、delete、update);
  • DQL数据查询语言:主要包含数据库中表数据的查询。(重头戏!);
  • DDL数据定义语言:主要是对数据库中表的操作,如创建表、删除表、修改表,即(create、drop、alter);
  • DCL数据控制语言:主要是对数据库用户的授权和撤销权限,即(grant、revoke);
  • TCL事务控制语言:事务控制语言,主要是对数据库中的事务的操作,事务的提交和回滚,即(commit、rollback)。

最最最重要的就是DQL了!TCL也很重要!


(此处忽略MySQL的安装,可问度娘)


2.MySQL命令

#创建数据库
create database 数据库名;
#使用数据库
use 数据库名;
#查询当前数据库
select database();
#查看有哪些数据库
show database;
#查看当前数据库中有哪些表(先使用数据库)
show tables;
#查看表的结构(查看表的字段、数据类型、长度、约束等等)
desc 表;
#查看创建表的语句
show create table 表名;
#删库跑路
drop 数据库名;

3.DQL(insert)

最最最重要的DQL来啦!

DQL不区分大小写。#、--、/**/都为注释。

字段查询

  • 查询整个表的数据
select * from tb_name;
  • 查询某个字段
select column_name from tb_name;
  • 查询多个字段
select column_name1,column_name2,... from tb_name;

给字段取别名

select column_name1 as 别名,... from tb_name;

条件查询

select column_name1,column_name2,... from tb_name where 条件;

where条件支持的运算符:

= 等于
<>或者!= 不等于
> 大于
>= 大于等于
< 小于
<= 小于等于
and 和,用于拼接多个条件,只有全部符合条件的数据才是结果
or 或,用于拼接多个条件,只要满足一个条件即可
in 或的升级,in(value1,value2),只要值为()中任意一个值即可
not 否定(如is not null,not in)
between...and... 在什么之间,前小后大,支持数字和字符
like 模糊查询,%代表任意个字符,_代表任意一个字符
is null 空,NULL为空,代表没有数据(区别于空串'')

去重

去重:去掉结果中重复的值,关键字为distinct。

select distinct column_name,... from tb_name where ...;

注意:distinct只能放在所有字段的最前方,支持多个字段去重,如果(distinct 字段1,字段2):意思为只有字段1和字段2的值都相等才会当作是重复的值。

排序

ASC(升序)、DESC(降序)。

默认升序。

select column_name,... from tb_name where... order by 字段名,... ASC或DESC

以上的执行顺序为:先from,再where,再select,再order by。

证明:可以对select后的字段使用别名,结果出来是别名,说明是select先执行,order by后执行。

可以多个字段同时进行排序,但是以前面的字段为主导,只有前面的字段值一样无法比较出大小时,才会使用后面的字段。

分组函数

分组函数有:

MAX(最大值),MIN(最小值),COUNT(记录总条数)、SUM(数据总和)、AVG(数据平均值)

select 分组函数(column_name),... from tb_name where...;

第一个重点:分组函数会忽略NULL值。可以使用if null(可能为null值的数据,当为null值时用什么替换null值)来解决NULL值计算带来的问题。

第二个重点:分组函数不能出现在where子句中。上面说过,where子句比select先执行,在where中使用分组函数就相当于用了还不存在的东西,肯定是不行的。

第三:count(*)为表的总记录条数,与字段无关。count(字段)为某个字段的条数,并且会忽略NULL值。

分组函数可以组合使用,即使用多个分组函数。

  • group by按某个字段进行分组
select column_name,分组函数(column_name),... from tb_name where... group by column_name;

以上的执行顺序为:from->where->group by->select

当没有group by时,整个表会自成一组。

第一个重点:group by一般和分组函数联合使用,并且一定在分组函数前执行。

第二个重点:当一条sql语句中有group by时,select后面只能跟group by后出现的字段和分组函数。

虽然出现了不是group by后面的字段不会报错,但是没有意义。Oracle该种情况就会直接报错。

多个字段可以联合使用,先按前面的字段分组,再按后面的字段进行分组。

  • having条件过滤

having和group by是一组的,只有有了group by才可以使用having,可以单独使用group by,但是不能单独使用having。

select column_name,分组函数(column_name),... from tb_name where... group by column_name having 条件;

以上的执行顺序为:from->where->group by->having->select

where先进行第一层的过滤,再分组之后,如果还需要进行筛选的话,就使用having。having的效率比where低,如果可以使用where的话,尽量使用where。

select	(5)
	xxx
from	(1)
	xxx
where	(2)
	xxx
group by (3)
	xxx
having	(4)
	xxx
order by
	xxx; (6)

数字为执行顺序。

连接查询

在实际的开发中,不可能只有一个表,而表与表之间,也常常都是有关联的。

(如果把所有的数据都放在一个表中的话,可能会有很多多余的数据,会造成表的数据十分的庞大。)

所以在实际的开发中,往往对应的需求都不是单表查询,而是查询多个表,即联表查询,即连接查询。

连接查询的分类:

  • 内连接
    • 等值连接;
    • 非等值连接;
    • 自连接。
  • 外连接
    • 左外连接(左连接);
    • 右外连接(右连接)。

先看几张表:

emp:员工表

​ 字段:员工编号empno,员工姓名ename,员工职位job,员工上级领导编号mgr,员工入职日期hiredate,员工工资sal,

​ 员工补贴comm,员工部门编号depyno;

dept:部门表

​ 字段:部门编号deptno,部门名称dname,部门所在地址loc;

salgrade:工资等级表

​ 字段:等级grade,最低工资losal,最高工资hisal。

连接查询的关键字为join,表1 join 表2(join 表3...) on 条件。可同时连接多个表。

笛卡尔积现象

两张表连接查询,没有任何的条件,结果数目为两张表总条数的乘积,这个现象称为笛卡尔积现象。

  • 内连接-等值连接
#如:查询每位员工所在的部门名称
#员工姓名在员工表中,部门名称在部门表中,所以需要联表查询
#可以通过员工表中的员工部门编号去部门表中查询
SELECT e.ename,d.dname FROM emp e INNER JOIN dept d ON  e.deptno = d.deptno;

给表使用别名的好处:因为两张表中可能有一样的字段,所以如果没有起别名的话,就会两张表都去查看是否有这个字段,降低效率,如果起了别名,指定了是哪张表,就只需要去指定的那张表中找,就可以提高效率了;并且两张表中有相同的数据,会产生混淆。

  • 内连接-非等值查询
#如:查询每位员工的薪资等级
#员工姓名在员工表中,薪资等级在工资等级表中
SELECT e.ename,s.grade FROM emp e JOIN salgrade s ON e.`SAL` BETWEEN s.losal AND hisal; 

内连接使用inner join...on,inner可以省略。

  • 内连接-自连接

把一张表看作两张表。

#如:查询每个员工的领导表,要求显示员工姓名和领导
#因为员工信息在emp表中,领导信息也在emp表中,所以emp既是员工表,又是领导表
#要先找到每位员工的领导编号,再通过领导编号去emp表中领导查对应的名字
SELECT e.ename '员工',t.ename '领导' FROM emp e JOIN (SELECT empno,ename FROM emp) t ON e.mgr= t.empno;

(这个可能需要多理解一下)

内连接与外连接的区别

内连接没有主表和副表之分,两个表的地位是一样的,内连接查询的是表之间能够匹配上的数据。

外连接有主表和副表之分,

左连接即左边的为主表,右连接即右边的表为主表(左连接有右连接的写法,右连接也有左连接的写法)

主要查询主表,捎带着查询副表,必须保证主表的完整,如果副表没有与主表匹配的数据,会自动填充NULL。

像上述查询每个员工的领导,因为有一个人肯定是没有领导的,如果是使用内连接,就会丢失掉这个大boss的信息,所以必须要使用外连接查询

  • 左连接
#如:还是上面的查询每位员工领导的例子
SELECT e.ename '员工',t.ename '领导' FROM emp e LEFT OUTER JOIN (SELECT empno,ename FROM emp) t ON e.mgr= t.empno;

outer可省略。

  • 右连接
#将上述例子改成右连接
SELECT e.ename '员工',t.ename '领导' FROM (SELECT empno,ename FROM emp) t RIGHT JOIN emp e ON e.mgr= t.empno;

多看看表中的数据和关系就能比较好的理解了(虽然本人也是菜鸟一枚)

三张表连接查询

#如:找出每一个员工的部门名称和薪资等级
#员工名称在员工表,部门名称在部门表,薪资等级在薪资表
#所以需要三张表连接查询
#先员工表和部门表查出员工姓名和部门名称,再员工表和和薪资等级表连接查询得出员工的薪资等级。
SELECT e.ename,d.dname,s.grade FROM emp e LEFT JOIN dept d ON e.`DEPTNO` = d.`DEPTNO`
LEFT JOIN salgrade s ON e.`SAL` BETWEEN s.`LOSAL` AND s.`HISAL`;

子查询

子查询就是使用多个select,其实上述连接查询的例子中,就已经使用了子查询了,在from后面。

子查询有三种形式:

  1. 在select后面;
  2. 在from后面;
  3. 在where后面。
  • select子查询
#如:找出每个员工所在的部门名称,要求显示员工名称和部门名称(使用join更简单,但是这里为了介绍select后面跟select语句)
SELECT e.ename,(SELECT d.dname FROM dept d WHERE e.deptno = d.deptno) AS deptname FROM emp e; 
  • from子查询

使用最多。

#如上述的内外连接。
  • where子查询
#找出高于平均薪资的员工(切记:where后面不能直接跟分组函数!)
SELECT ename FROM emp WHERE sal >(SELECT AVG(sal) FROM emp);

union

union是连接查询,可以将查询结果拼接起来:

#找出工作岗位是CLERK和SALESMAN的员工(可以使用or、in,也可以使用union)
(SELECT ename FROM emp WHERE job = 'CLERk') UNION (SELECT ename FROM emp WHERE job = 'SALESMAN');

注意:mysql不区分大小写,但是,表中的数据严格区分大小写!

分页

分页很重要!

limit 该页开始的下标,该页的条数;
#下标从0开始,若下标是0,可以省略

#如:找出员工表中前五条数据
SELECT * FROM emp LIMIT 5;
#找出员工表中第6-10条数据
SELECT * FROM emp LIMIT 5,5;

所以这里涉及到了一个计算的问题,如何根据给定的页数和条数计算出起始下标(在实际开发中,都是以参数的形式传递页码的)

limit (pageNo-1)* pageSize, pageSize (pageNo为页码,pageSize为每页条数)


以上涉及到的执行顺序总结:

select	  (5)
	xxx			#*、字段、去重、分组函数、字段别名
from	  (1)
	xxx			#单表、多表、连表join
where	  (2)
	xxx			#支持的运算符 = <>或!= > < >= <= and or in not (is null) like between...and... 
group by  (3)
	xxx			#单字段、多字段
having    (4)
	xxx			#与group by联合使用,接条件
order by  (6)	
	xxx			#ASC DESC
limit	  (7)
	xxx			#分页
posted @ 2021-02-26 10:57  deng-hui  阅读(165)  评论(0编辑  收藏  举报