05 MySQL表的增删查改

本文详细介绍了SQL中的基本操作,包括插入数据、更新与替换记录、查询表信息以及更新和删除数据。重点讨论了SELECT查询的多种方式,如全列查询、指定列查询、条件过滤、结果排序和分页查询,还深入讲解了聚合函数、GROUP BY子句的使用。此外,文章探讨了子查询、多表查询、自连接以及内外连接的应用,为数据库操作提供全面指导。
摘要由CSDN通过智能技术生成

之前的 对数据表的操作 主要是进行列的增删查改,这里要对每条数据进行增删查改。
CRUD 即增加(Create)、查询(Retrieve)、更新(Update)、删除(Delete)四个单词的首字母缩写。

具体语句的执行顺序为: from子句->where 子句->group by 子句->having 子句->select 子句->order by 子句。 后面子句的别名不能在前面的子句使用。


一、插入数据

增加数据:
1.全列增加 insert into [表名称] values(表字段对应的值)
		
2.指定列进行插入 insert into[表名称] (表中列的名称,...) values(指定表字段对应的值...)
		
3.一次性插入多行数据 
insert into[表名称] (表中列的名称,...) values(指定表字段对应的值...),(指定表字段对应的值...)
insert into [表名称] values(表字段对应的值),(表字段对应的值)

在这里插入图片描述

1.1. 插入查询结果

也可以将一个表的查询结果插入到另一个表中。
在这里插入图片描述


二、表的更新和替换

由于 主键 或者 唯一键 对应的值已经存在而导致插入失败,此时可以使用更新或者替换来进行解决。

2.1. 表的更新

insert ... on duplicate key updata old value = new value...	

在这里插入图片描述

2.2. 替换

replace into 和 insert into的用法是类似的,insert每次插入一条新的数据,replace 会先查看表中是否有这条数据(主键或者唯一键),如果有先删除,然后插入一条新的数据,如果不存在则直接插入一条新的数据。

根据表中的主键或唯一键来判断,如果表中没有主键或唯一索引,那么replace into 就相当于 insert into,会直接插入一条数据。

在这里插入图片描述


三、select表的查询

3.1. 全列查询

select *from [表名称];‘ * '表示当前表的所有列。对于字段比较少,并且插入数据比较少的表,可以使用全列查询,查询的效率不会收到太大影响。如果一个表中字段比较多,或者数据量比较大,则全列查询会导致查询效率降。

3.2. 指定列查询

select [字段名称] …,from [表名称];
在这里插入图片描述

3.3. 查询字段为表达式并取别名

在这里插入图片描述

注意:这里math+10只是将查询结果+10,并不会改变表中的math。

在这里插入图片描述

3.4. 结果去重

加上关键字distinct进行查询。
在这里插入图片描述

3.4. where条件

比较运算符:

运算符说明
<, <= ,>,>=,小于,小于等于,大于,大于等于
=等于,NULL 不安全,例如 NULL = NULL 的结果是 NULL
<=>等于,NULL 安全,例如 NULL <=> NULL 的结果是 TRUE(1)
!=, <>不等于
between a0 and a1范围匹配,[a0, a1],如果 a0 <= value <= a1,返回 TRUE(1)
IN (option, …)如果是 option 中的任意一个,返回 TRUE(1)
IS NULL是 NULL
IS NOT NULL不是 NULL
LIKE 模糊匹配。% 表示任意多个(包括 0 个)任意字符;_ 表示任意一个字符

逻辑运算符:

运算符说明
AND多个条件必须都为 TRUE(1),结果才是 TRUE(1)
OR任意一个条件为 TRUE(1), 结果为 TRUE(1)
NOT条件为 TRUE(1),结果为 FALSE(0)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

注意:别名不能出现在where条件中。因为查找的时候,是根据条件(where后面的条件)找的,即查找的时候是先看到条件,根据条件找到内容后,再根据select后面的语句进行显示。所以在查找的时候并不知道别名。

不过在from后对表取别名是可以的。

在这里插入图片描述

在这里插入图片描述

3.5. 结果排序

order by +排序条件 +排序方式;

order by子句中可以使用列别名。

ASC(默认方式)按照升序查询,DESC按照降序查询。

NULL 视为比任何值都小,降序出现在最下面。
在这里插入图片描述

在这里插入图片描述

3.6. 分页查询

对未知表进行查询时,最好加一条 limit 1,避免因为表中数据过大,查询全表数据导致数据库卡死。

limit +数字(显示多少行) offset +数字(偏移量);
或者
limit+数字(偏移量)+数字(显示多少行);

在这里插入图片描述

在这里插入图片描述

这两种写法的偏移量和行数进行了颠倒,但是当只有一个数字的时候,比如limit 5,它们显示的都是一样的,即显示前5行。


四、update表的更新

4.1. 对查询到的结果进行列值更新

上面的更新涉及到插入操作,如果只是单纯地想更新已经存在的内容,则可以使用下面的命令。
update + 表名 + set + 更改的列=新的值 where 限制条件
如果不加限制条件,则会将所有的列都会改掉。

在这里插入图片描述

在这里插入图片描述


五、delete删除表中的数据

删除的基本单位是一行,如果只是删除一行中的某一信息,则可以使用update进行清空。
delete from 表名+ where 限制条件;

如果不加限制条件,则会将整个表的数据都会删除,但是表还在。
drop table 表名;才是将整个表都删除。

在这里插入图片描述

5.1. 截断表

truncate 表名;可以直接将表名进行清空,它与delete有一些区别:

  1. 只能对整表操作,不能像 delete一样针对部分数据操作。
  2. 实际上 MySQL 不对数据操作,所以比 delete更快,但是truncate 在删除数据的时候,并不经过真正的事物,所以无法回滚。
  3. 会重置auto_increment项。

六、聚合函数

函数说明
COUNT([DISTINCT] expr)返回查询到的数据的 数量
SUM([DISTINCT] expr)返回查询到的数据的 总和,会忽略null和非数字
AVG([DISTINCT] expr)返回查询到的数据的 平均值,会忽略null和非数字
MAX([DISTINCT] expr)返回查询到的数据的 最大值,如果没有结果则返回null
MIN([DISTINCT] expr)返回查询到的数据的 最小值,如果没有结果则返回null

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


七、group by子句的使用

group by 子句用来进行分组。

采用如下经典的测试用例表:
scott_data.sql:

DROP database IF EXISTS `scott`;
CREATE database IF NOT EXISTS `scott` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

USE `scott`;

DROP TABLE IF EXISTS `dept`;
CREATE TABLE `dept` (
  `deptno` int(2) unsigned zerofill NOT NULL COMMENT '部门编号',
  `dname` varchar(14) DEFAULT NULL COMMENT '部门名称',
  `loc` varchar(13) DEFAULT NULL COMMENT '部门所在地点'
);


DROP TABLE IF EXISTS `emp`;
CREATE TABLE `emp` (
  `empno` int(6) unsigned zerofill NOT NULL COMMENT '雇员编号',
  `ename` varchar(10) DEFAULT NULL COMMENT '雇员姓名',
  `job` varchar(9) DEFAULT NULL COMMENT '雇员职位',
  `mgr` int(4) unsigned zerofill DEFAULT NULL COMMENT '雇员领导编号',
  `hiredate` datetime DEFAULT NULL COMMENT '雇佣时间',
  `sal` decimal(7,2) DEFAULT NULL COMMENT '工资月薪',
  `comm` decimal(7,2) DEFAULT NULL COMMENT '奖金',
  `deptno` int(2) unsigned zerofill DEFAULT NULL COMMENT '部门编号'
);


DROP TABLE IF EXISTS `salgrade`;
CREATE TABLE `salgrade` (
  `grade` int(11) DEFAULT NULL COMMENT '等级',
  `losal` int(11) DEFAULT NULL COMMENT '此等级最低工资',
  `hisal` int(11) DEFAULT NULL COMMENT '此等级最高工资'
);


insert into dept (deptno, dname, loc)
values (10, 'ACCOUNTING', 'NEW YORK');
insert into dept (deptno, dname, loc)
values (20, 'RESEARCH', 'DALLAS');
insert into dept (deptno, dname, loc)
values (30, 'SALES', 'CHICAGO');
insert into dept (deptno, dname, loc)
values (40, 'OPERATIONS', 'BOSTON');

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7369, 'SMITH', 'CLERK', 7902, '1980-12-17', 800, null, 20);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20', 1600, 300, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7521, 'WARD', 'SALESMAN', 7698, '1981-02-22', 1250, 500, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7566, 'JONES', 'MANAGER', 7839, '1981-04-02', 2975, null, 20);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28', 1250, 1400, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01', 2850, null, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7782, 'CLARK', 'MANAGER', 7839, '1981-06-09', 2450, null, 10);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7788, 'SCOTT', 'ANALYST', 7566, '1987-04-19', 3000, null, 20);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7839, 'KING', 'PRESIDENT', null, '1981-11-17', 5000, null, 10);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7844, 'TURNER', 'SALESMAN', 7698,'1981-09-08', 1500, 0, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7876, 'ADAMS', 'CLERK', 7788, '1987-05-23', 1100, null, 20);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7900, 'JAMES', 'CLERK', 7698, '1981-12-03', 950, null, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7902, 'FORD', 'ANALYST', 7566, '1981-12-03', 3000, null, 20);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7934, 'MILLER', 'CLERK', 7782, '1982-01-23', 1300, null, 10);

insert into salgrade (grade, losal, hisal) values (1, 700, 1200);
insert into salgrade (grade, losal, hisal) values (2, 1201, 1400);
insert into salgrade (grade, losal, hisal) values (3, 1401, 2000);
insert into salgrade (grade, losal, hisal) values (4, 2001, 3000);
insert into salgrade (grade, losal, hisal) values (5, 3001, 9999);

导入数据库:
在这里插入图片描述
在这里插入图片描述

显示每个部门的平均工资和最高工资:

先对部门进行分组,然后使用聚合函数即可求出平均工资和最高工资。
在这里插入图片描述

显示每个部门的每种岗位的平均工资和最低工资:

首先按照部门进行分组,然后再对部门按照岗位分组。

在这里插入图片描述

7.1. 分组后使用聚合函数

显示平均工资低于2000的部门和它的平均工资:

  1. 首先统计各个部门的平均工资:
    在这里插入图片描述

  2. 然后在这些部门中找出小于2000工资的部门:
    错误写法:
    在这里插入图片描述
    正确写法:
    在这里插入图片描述

这主要是因为where后的条件表达式里不允许使用聚合函数,原因如下:

  • where是一行一行检查的,筛选出符合条件的行,当全部行检查完才会形成一张新的表,也就是结果集,而聚合函数需要对结果集的某一列的全部值进行运算(比如求最大值、平均值)。 因此两者冲突(在执行聚合函数时并没有结果集),不能同时使用。
  • having则是分组(group by)后,在组内进行筛选,此时可以使用聚合函数。
  • 具体语句的执行顺序为: from子句->where 子句->group by 子句->having 子句->select 子句->order by 子句。

求有两个以上岗位工资小于3000的部门号,以及该部门的平均工资:

错误写法:
在这里插入图片描述

这种写法先对sal进行筛选(sal<3000),将筛选出来的元组按照部门号进行分组,然后过滤出组内元组条数大于2条的部门分组。但是接下来求avg(sal)则是对这些已经进行sal<3000筛选的部门分组进行求平均值,这些分组中每个元组的sal都是小于3000的,并不是该部门的全部元组。

正确写法:
在这里插入图片描述

这种写法用到了子查询,首先查出 有两个以上岗位工资小于3000的部门号 ,然后再用in过滤出属于这些部门号中的元组,然后按照部门号分组,此时我们就拿到这些部门号内的所有元组,而不是sal小于3000的元组。


八、复合查询

8.1. 子查询

子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询。

显示工资最高的员工的名字和工作岗位

在这里插入图片描述

先找出emp表中最高的工资,然后在查找时找工资为最高工资的元组。

显示工资高于平均工资的员工信息

在这里插入图片描述

先求出emp表中的平均工资,然后在查找时找工资高于平均工资的元组。

8.1.1. 多行子查询

多行子查询是指子查询的结果返回单列多行数据

  • in关键字:只要在多行单列的结果中,则条件满足。

查询和10号部门的工作岗位相同的雇员的名字,岗位,工资,部门号,但是不包含10号自己。

首先找出10号部门的所有job,然后判断emp中job是否在所查询到的job中,并且部门号要不等于10。
在这里插入图片描述

  • all :需要满足多行单列结果当中的所有,条件才满足。

显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号。

找出部门30的所有员工的工资,然后emp表中sal要比这些工资都高。
在这里插入图片描述

  • any :只要满足多行单列结果当中的任一一个,则条件满足

显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号(包含自己部门的员工)。

找出部门30号的所有员工的工资,然后emp表中sal要比这些工资任意一个高就可以。

当然也可以找出30号部门的最小工资,然后emp表中sal比这个最小工资大。
在这里插入图片描述

8.1.2. 多列子查询

多列子查询则是指查询返回多个列数据的子查询语句。

查询和SMITH的部门和岗位完全相同的所有雇员,不含SMITH本人。

我们需要同时找到deptno和job两列数据,上面的多行子查询都只是包含一列数据。

在这里插入图片描述

8.2. 在from子句中使用子查询

子查询语句出现在from子句中。这里要用到数据查询的技巧,把一个子查询当做一个临时表使用。

显示每个高于自己部门平均工资的员工的姓名、部门、工资、平均工资。

  1. 首先,我们可以求出每个员工的姓名、部门、工资、平均工资:
    但是这样有问题,平均工资是所有员工的平均工资,而ename和deptno则属于每个员工,所以它们冲突了,不能同时显示。
    在这里插入图片描述

  2. 为了解决上面的问题,我们可以先按照部门进行分组,然后求出平均工资,然后和emp表进行笛卡尔积,然后根据部门号进行过滤。这样就找出了每个人的姓名、部门、工资,以及自己所在部门的平均工资。
    在这里插入图片描述

  3. 最后找高于自己部门平均工资的员工,只需要在where后再加一个条件即可
    在这里插入图片描述

查找每个部门工资最高的人的姓名、工资、部门、最高工资。

先按部门分组然后找出最高工资和部门号,然后和emp进行笛卡尔积,最后过滤。

在这里插入图片描述

显示每个部门的信息(部门名,编号,地址)和人员数量。

  • 使用多表解决:
  1. 将员工表与部门表进行笛卡尔积,这样就能够拿到每个员工对应的部门信息
    在这里插入图片描述

  2. 然后对部门号、部门名称、部门地址进行分组,并统计个数
    在这里插入图片描述

  • 使用子查询
  1. 对员工表表的人按照部门号进行分组并统计个数
    在这里插入图片描述

  2. 将上面的表当成临时表,和员工表进行笛卡尔积,同时过滤。
    在这里插入图片描述

8.3. 多表查询

实际开发中往往数据来自不同的表,所以需要多表查询。

显示雇员名、雇员工资以及所在部门的名字。

因为上面的数据来自emp和dept表,因此要联合查询。
在这里插入图片描述

在查找时,会先将两张表进行笛卡尔积,然后再从进行笛卡尔积之后的大表中根据where的限制条件找出合适的元组。
在这里插入图片描述

显示部门号为10的部门名,员工名和工资。

和上一个类似,但是限制条件中要多加一个部门号为10

在这里插入图片描述

显示各个员工的姓名,部门名称,工资,及工资级别。

涉及到三张表的查询
在这里插入图片描述

8.4. 自连接

自连接是指在同一张表连接查询,也就是自己和自己做笛卡尔积。
自连接时要对表进行重命名,否则会出现名字冲突的问题。

显示员工FORD的上级领导的编号和姓名(mgr是员工领导的编号)

可以使用子查询,先找出FORD的mgr字段然后再查找工号等于mgr。

也可以使用自连接,将leader表和worker表进行笛卡尔积,然后worker表中的mgr字段等于leader表中的empno同时worker表中的ename等于FORD。
在这里插入图片描述

8.5. 合并查询

在实际应用中,为了合并多个select的执行结果,可以使用集合操作符 union,union all。union默认去重,union all是不去重。

实际上合并查询也可以在where中使用or来完成。

将工资大于2500或职位是MANAGER的人找出来。

在这里插入图片描述


九、表的内外连接

9.1. 内连接

内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选,上面的多表查询都是内连接,也是在开发过程中使用的最多的连接查询。

select 字段 from 表1 inner join 表2 on 连接条件 and 其他条件;

显示SMITH的名字和部门名称。

在这里插入图片描述

这两种写法都可以,但是它们还是有一些区别:

  1. where是先生成两张表的笛卡尔积,然后根据where后面的条件进行过滤。
  2. inner join ... on 条件则是根据后面的条件on emp.deptno=dept.deptno and ename='SMITH',在生成笛卡尔积时就进行过滤,不满足这些条件的元组不会生成笛卡尔积。
  3. 并且on后面的and如果改成where,它们的意义也不同。改成where以后,它们在 inner join ... on 条件根据的条件则是on emp.deptno=dept.deptno,然后根据where ename='SMITH'进行过滤。
    在这里插入图片描述

9.2. 外连接

外连接分为左外连接和右外连接。

9.2.1. 左外连接

如果联合查询,左侧的表完全显示我们就说是左外连接。
select 字段名 from 表名1 left join 表名2 on 连接条件;

比如对于下面两张表:
在这里插入图片描述

使用左连接时,当左边表和右边表没有匹配时,也会显示左边表的数据:
在这里插入图片描述

9.2.2. 右外连接

如果联合查询,右侧的表完全显示我们就说是右外连接。
select 字段 from 表名1 right join 表名2 on 连接条件;

使用右连接时,当左边表和右边表没有匹配时,也会显示右边表的数据:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天也要写bug、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值