目录
一,表的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筛选若干条记录进行显示