目录
一,表的CRUD
二,Create新增
2.1 SQL介绍
2.2 按行和列插入
2.3 插入否则更新
2.4 插入替换
三,Retrieve查找
3.1 SQL介绍
3.2 按列查询
3.3 查询字段为表达式
3.4 结果去重
3.5 where关键字
3.6 对结果排序
3.7 分页显示
四,update修改
五,Delete删除
5.1 常规删除
5.2 删除整张表数据
5.3 截断表
六,其它操作
6.1 去重表数据
6.2 聚合统计
6.3 分组聚合
6.3.1 生成测试内容
6.3.2 演示
6.3.3 having条件
6.4 SQL中各语句执行顺序
一,表的CRUD
表的增删查改简称CRUD:
- Create(新增),对应SQL为insert
- Retrieve(查找),对应SQL为select
- Update(修改),对应SQL为update
- Delete(删除),对应SQL为delete
CRUD的操作对象是表中的数据,是典型的数据操作语言(Data Manipulation Language)
二,Create新增
2.1 SQL介绍
INSERT [INTO] table_name [(column1 [, column2] ...)] VALUES (value_list1) [, (value_list2)] ...;
- 上面SQL中的每个value_list都表示插入的一条记录,每个value_list都由若干待插入的列值组成
- column用于指定每个value_list里的值分别插入到表中的哪一列
为了方便后续演示,我们先建一个表,如下:
2.2 按行和列插入
①首先是基本插入,我们前面的博客已经演示过很多次了,如下:
②我们还可以一次插入多条数据
2.3 插入否则更新
- 当插入的数据中有列值与已有的主键列值冲突,则会插入失败
- 那么我们可以让插入的主键相同时,更新其它列值,如下演示
如果主键不冲突,那么就会正常插入
- 0 rows affected:表中有冲突数据,但冲突数据的值和指定更新的值相同。
- 1 row affected:表中没有冲突数据,数据直接被插入。
- 2 rows affected:表中有冲突数据,并且数据已经被更新。
2.4 插入替换
替换数据的效果和上面的插入否则更新其实很像:
- 如果表中没有冲突数据,则直接插入数据
- 如果有冲突数据,先将冲突数据删除,再插入新数据
只要把SQL中的insert替换成replace即可:
三,Retrieve查找
3.1 SQL介绍
SELECT [DISTINCT] {* | {column1 [, column2] ...}} FROM table_name [WHERE ...] [ORDER BY ...] [LIMIT ...];
- { }中的 | 代表可以选择左侧的语句或右侧的语句。
为了方便后续演示,我们先创建一个成绩表,并往里面预先插入一些数据:
3.2 按列查询
我们前面用的select * from就是全列查询,其实我们可以把 * 换成指定列的字段名,实现按需求指定列查询,如下:
3.3 查询字段为表达式
select这个语句非常特殊,后面接的是表达式,我们可以把表达式计算,然后显示出来
所以我们可以用这个特性计算表中每位同学的总分,如下:
as关键字也可以省略,如下:
3.4 结果去重
我们可以在select关键字的后面加上distinct对查询结果进行去重:
3.5 where关键字
前面说过select这个关键字很特殊,它后面跟的是一个表达式,其中where关键字就是表达式中一个非常重要的成员:
- 如果在查询数据时没有指定where子句,那么会直接将表中所有的记录作为数据源来依次执行select语句
- 如果在查询数据时指定了where子句,那么在查询数据时会先根据where子句筛选出符合条件的记录,然后将符合条件的记录作为数据源来依次执行select语句。
where子句中可以指明一个或多个筛选条件,各个筛选条件之间用逻辑运算符AND或OR进行关联,常用的运算符如下:
比较运算符:
比较运算符 | 解释 |
---|---|
>、>=、<、<= | 和C/C++一样 |
= | 等于。但是NULL不安全,例如NULL=NULL的结果是NULL而不是TRUE(1) |
<=> | 等于。NULL安全,例如NULL<=>NULL的结果就是TRUE(1) |
!=、<> | 不等于 |
between a0 and a1 | 范围匹配。如果a0 <= value <= a1,则返回TRUE(1) |
in(option1, option2, ......) | 如果是括号中的任意一个option,则返回TRUE(1) |
is null | 如果是NULL,则返回TRUE(1) |
is not null | 如果不是NULL,则返回TRUE(1) |
like | 模糊匹配。% 表示任意多个字符(包括0个),_ 表示任意一个字符 |
逻辑运算符:
逻辑运算符 | 解释 |
---|---|
and | 当多个条件同时为TRUE(1)时,结果为TRUE(1),否则为FALSE(0) |
or | 任意一个个条件为TRUE(1)时,结果为TRUE(1),否则为FALSE(0) |
not | 条件为TRUE(1)时,结果为TRUE(1);条件为FALSE(0)时,结果为FALSE(0),就是取反 |
下面我们将通过部分例子来熟悉where的使用方法:
①找出英语成绩不及格的同学名字和英语成绩
②找出语文成绩在 [80, 90] 之间的同学名字和语文成绩
③找数学成绩是58或者59或者98或者99分的同学姓名和数学成绩
④找姓孙的同学
有时候我们并不能确定字段具体的细节含义,所以可以采用模糊搜索:
⑤找语文成绩好于英语成绩的同学
⑥找总分在200分以下的同学
错误分析:
- 我们的原意是将三科成绩加起来然后重命名为total,然后根据where判断total小于200的结果,但是结果报错
- 因为SQL语句是有执行顺序的,最先执行from语句,指明我要在哪个表里面查
- 然后执行where语句,表明少选条件是什么,再去表里面查
- 最后就是执行as语句修改列名,并且as只是在显示层面上进行修改
- 所以报错显示total不存在,就是因为它是先执行的where语句再执行的as语句
下面是正确示范:
⑦找出语文成绩大于80分且不姓孙的同学
⑧找孙某同学,或者要求总成绩>200并且语文成绩<数学成绩并且英语成绩>80
3.6 对结果排序
排序有三种:ASC升序,DESC降序,如果加了order by但是不写什么顺序,则默认是ASC排升序
①找同学数学成绩,按升序显示
②找同学总分,由高到低显示(降序)
③找姓孙或姓曹的同学的数学成绩,结果按照数学成绩由高到低显示
注意:如果字段是NULL,则order by对于NULL是作为最小值处理
3.7 分页显示
①显示成绩表的前五行
②limit n1, n2; 默认从n1的下一行开始显示 n2 行
③找总分第一的同学
④找总分第二名和第三名的同学
四,update修改
我们直接通过例子来学习修改的步骤
①将孙悟空同学的数学成绩修改成80分
②将曹孟德的数学成绩变为60,语文成绩变为70
③将总成绩倒数前三的3位同学的数学成绩加上30分
④将所有同学的语文成绩翻倍
五,Delete删除
5.1 常规删除
注意:任何删除都要考虑再考虑,确认万无一失再进行删除
①删除孙悟空同学的考试成绩
②删除总分最低同学的成绩
5.2 删除整张表数据
为了方便测试我们创建一个测试表并提前插入些数据:
①在delete语句中只指明表名,没有任何where等筛选条件,这时会删除整张表的数据,注意只是删除数据,表结构不受影响
②此时再插入数据时,如果不指明自增长字段的值,那么后续插入的数据的自增长的值是在之前的基础上继续增长的:
这是因为我们创建表时添加了自增长字段,该字段不会随着delete的执行而删除或重置,会在原来自增长数的基础上继续增长:
5.3 截断表
截断表的SQL如下:
TRUNCATE [TABLE] table_name;
-
truncate只能对整表操作,不能像delete一样针对部分数据操作。
-
truncate实际上不对数据操作,所以比delete更快。
-
truncate在删除数据时不经过真正的事务,所以无法回滚。
-
truncate会重置AUTO_INCREMENT字段。
我们仍然创建一个测试表,并预先插入一些数据方便演示:
①truncate语句只指明要删除数据的表名,和delete一样,也是会删除整张表的数据;但是truncate是对表做操作,所以truncate语句执行后看到影响行数为0
②截断表也会重置自增长字段
六,其它操作
6.1 去重表数据
创建测试表并插入数据,包含重复数据:
在select后面加上distinct即可进行去重,但是只是对查询结果进行去重,不影响表原数据
所以我们要对表数据进行去重,需要进行下面的步骤:
①先查数据,然后去重,就是上面的图片一样
②建一个新表,把上面做去重的数据插入
③最后重命名旧表,把新表的名字改成旧表的,即可完成表数据去重
6.2 聚合统计
简单来说就是统计相关的函数,如下演示:
①统计成绩表学生个数
②也可以总计综合,比如数学总分
③也可以求数学平均分
④求总分平均分
⑤也有聚合函数可以求最大或最小值
注意:聚合是有条件的,要保证数据列是可被聚合的,只属于一个人的信息是无法聚合的,比如张三和平均值无法聚合
6.3 分组聚合
6.3.1 生成测试内容
我们先创建一个雇员信息表,其内部包含三张表:员工表(emp)、部门表(dept)和工资等级表(salgrade)
员工表包含下面字段:
- 雇员编号(empno)
- 雇员姓名(ename)
- 雇员职位(job)
- 雇员领导编号(mgr)
- 雇佣时间(hiredate)
- 工资月薪(sal)
- 奖金(comm)
- 部门编号(deptno)
部门表(dept)中包含如下字段:
- 部门编号(deptno)
- 部门名称(dname)
- 部门所在地点(loc)
工资等级表(salgrade):
- 等级(grade)
- 此等级最低工资(losal)
- 此等级最高工资(hisal)
我们需要用到的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);
上述SQL是先创建了一个名为scott的库,然后创建了三张表并插入了部分数据,我们可以将上述内容保存在Linux一个目录中,然后再MySQL中使用source命令就可以一键执行文件中的SQL:
部门表的结构和内容如下:
员工表的内容如下:
工资等级表内容如下:
6.3.2 演示
分组聚合我们用到的关键字是group by,具体用法直接看后面演示:
①显示每个部门的每种岗位的平均工资和最高工资
②显示每个部门的每种岗位的平均工资和最低工资
- group by的子句中可以指明多个字段进行分组,各个字段之间使用逗号隔开,分组优先级与书写顺序相同。
6.3.3 having条件
having可以指明一个或多个筛选条件
having和where的区别:
- where子句放在表名后面,而having必须搭配group by使用,放在group by子句的后面
- where子句是对整表的数据进行筛选,having子句是对分组后的数据进行筛选
- where子句中不能使用聚合函数和别名,而having子句中可以使用聚合函数和别名
①显示平均工资低于2000的部门和它的平均工资
- 先统计每个部门的平均工资
- 然后通过having筛选出低于2000的部门
6.4 SQL中各语句执行顺序
-
根据where筛选出符合条件的记录
-
根据group by对数据进行分组
-
将分组后的数据依次执行select语句
-
根据having对分组后的数据进行进一步筛选
-
根据order by对数据进行排序
-
根据limit筛选若干条记录进行显示