MySQL表的增删改查
表的增删查改简称CRUD:Create(新增),Retrieve(查找),Update(修改),Delete(删除)。
CRUD的操作对象是对表当中的数据,是典型的DML(Data Manipulation Language)数据操作语言。
Create
基本语法:
INSERT [INTO] table_name [(column1 [, column2] ...)] VALUES (value_list1) [, (value_list2)] ...;
参数说明:
- SQL中大写的表示关键字,[ ]中代表的是可选项。
- SQL中的每个value_list都表示插入的一条记录,每个value_list都由若干待插入的列值组成。
- SQL中的column列表,用于指定每个value_list中的各个列值应该插入到表中的哪一列。
下面创建一个学生表,表当中包含自增长的主键id、学号、姓名和QQ号。
查看表结构如下:
单行数据 + 全列插入
接下来我们使用insert命令向表中插入数据,插入两条记录,value_list 数量必须和定义表的列的数量及顺序一致。注意,这里在插入的时候,也可以不用指定id(当然,那时候就需要明确插入数据到那些列了),那么mysql会使用默认的值进行自增。
多行数据 + 指定列插入
insert命令也可以向表中插入多行数据,此时插入的多条记录要使用逗号隔开,同时也可以指定列进行插入。
插入否则更新
向表中插入数据会出现由于 主键 或者 唯一键 对应的值已经存在而导致插入失败。
主键冲突
唯一键冲突
此时可以选择性的进行同步更新操作语法:
- 如果表中没有冲突数据,则直接插入数据。
- 如果表中有冲突数据,则将表中的数据进行更新。
基本语法如下:
INSERT ... ON DUPLICATE UPDATE column1=value1 [, column2=value2] ...;
比如向学生表中插入记录时,如果没有出现主键冲突则直接插入记录,如果出现了主键冲突,则将表中冲突记录的学号和姓名进行更新。
其中:
- 0 row affected: 表中有冲突数据,但冲突数据的值和 update 的值相等;
- 1 row affected: 表中没有冲突数据,数据被插入;
- 2 row affected: 表中有冲突数据,并且数据已经被更新;
通过 MySQL 函数我们可以获取受到影响的数据行数。
替换
- 主键 或者 唯一键 没有冲突,则直接插入;
- 主键 或者 唯一键 如果冲突,则删除后再插入。
此时需要用到的就是我们的 replace SQL语句。
其中:
- 1 row affected: 表中没有冲突数据,数据被插入;
- 2 row affected: 表中有冲突数据,删除后重新插入。
Retrieve
基本语法:
SELECT [DISTINCT] {* | {column1 [, column2] ...}} FROM table_name [WHERE ...] [ORDER BY ...] [LIMIT ...];
下面创建一个成绩表,表当中包含自增长的主键id、姓名以及该同学的语文成绩、数学成绩和英语成绩。
接下来我们向表中插入一部分数据:
SELECT 列
全列查询
在前面的使用中我们通常使用*
进行全列查询,但是通常情况下不建议进行全列查询,因为:
- 查询的列越多,意味着需要传输的数据量越大;
- 可能会影响到索引的使用。
指定列查询
指定列的顺序不需要按定义表的顺序来,列与列之间使用逗号隔开就可以了。
查询字段为表达式
表达式不包含字段
表达式包含一个字段
表达式包含多个字段
为查询结果指定别名
基本语法:
SELECT column [AS] alias_name [...] FROM table_name;
有的查询结果可能不太能体现我们需要表达的意思,我们可以取别名。
结果去重
比如我们在查询成绩时发现有两个人是成绩是重复的,此时我们想要去除重复值,就需要使用到 distinct SQL语句。
WHERE 条件
添加where子句的区别:
- 如果在查询数据时没有指定where子句,那么会直接将表中所有的记录作为数据源来依次执行select语句。
- 如果在查询数据时指定了where子句,那么在查询数据时会先根据where子句筛选出符合条件的记录,然后将符合条件的记录作为数据源来依次执行select语句。
where子句中可以指明一个或多个筛选条件,各个筛选条件之间用逻辑运算符AND或OR进行关联,下面给出了where子句中常用的比较运算符和逻辑运算符。
比较运算符:
运算符 | 说明 |
---|---|
<、<=、>、>= | 小于、小于等于、大于、大于等于 |
= | 等于。NULL不安全,例如NULL=NULL的结果是NULL而不是TRUE(1) |
<=> | 等于。NULL安全,例如NULL<=>NULL的结果就是TRUE(1) |
!=、<> | 不等于 |
BETWEEN a0 AND a1 | 范围匹配。如果a0<=value<=a1,则返回TRUE(1) |
IN(option1,option2,…) | 如果是IN中的任意一个option,则返回TRUE(1) |
IS NULL | 如果是NULL,则返回TRUE(1) |
IS NOT NULL | 如果不是NULL,则返回TRUE(1) |
LIKE | 模糊匹配。%表示任意多个字符(包括0个),_表示任意一个字符 |
逻辑运算符:
运算符 | 说明 |
---|---|
AND | 多个条件必须都为 TRUE(1),结果才是 TRUE(1) |
OR | 任意一个条件为 TRUE(1), 结果为 TRUE(1) |
NOT | 条件为 TRUE(1),结果为 FALSE(0) |
英语不及格的同学及英语成绩 ( < 60 )
语文成绩在 [80, 90] 分的同学及语文成绩
使用 AND 进行条件连接:
使用 BETWEEN … AND … 条件:
数学成绩是 58 或者 59 或者 98 或者 99 分的同学及数学成绩
使用 OR 进行条件连接:
使用 IN 条件:
姓孙的同学 及 孙某同学
% 匹配任意多个(包括 0 个)任意字符:
_ 匹配严格的一个任意字符:
语文成绩好于英语成绩的同学
WHERE 条件中比较运算符两侧都是字段。
总分在 200 分以下的同学
注意:
- 在where子句中不能使用select中指定的别名;
- 查询数据时是先根据where子句筛选出符合条件的记录;
- 然后再将符合条件的记录作为数据源来依次执行select语句。
where子句的执行是先于select语句的,所以在where子句中不能使用别名,如果在where子句中使用别名,那么在查询数据时就会产生报错。
语文成绩 > 80 并且不姓孙的同学
孙某同学,否则要求总成绩 > 200 并且 语文成绩 < 数学成绩 并且 英语成绩 > 80
NULL 的查询
我们在刚刚创建的students表中查询qq号已知的同学。
查询qq号未知的同学。
我们需要注意的是与NULL值比较,不能使用=
,需要使用<=>
,使用=运算符无法得到正确的查询结果。
结果排序
基本语法:
SELECT ... FROM table_name [WHERE ...] ORDER BY column [ASC | DESC] [, ...];
- ASC 为升序(从小到大);
- DESC 为降序(从大到小);
- 默认为 ASC。
注意:没有 ORDER BY 子句的查询,返回的顺序是未定义的,永远不要依赖这个顺序;
同学及数学成绩,按数学成绩升序显示
同学及 qq 号,按 qq 号排序显示
NULL 视为比任何值都小,升序出现在最上面:
NULL 视为比任何值都小,降序出现在最下面:
查询同学各门成绩,依次按 数学降序,英语升序,语文升序的方式显示
多字段排序,排序优先级随书写顺序:
说明一下:
- order by子句中可以指明按照多个字段进行排序,每个字段都可以指明按照升序或降序进行排序,各个字段之间使用逗号隔开,排序优先级与书写顺序相同。
- 比如上述SQL中,当两条记录的数学成绩相同时就会按照英语成绩进行排序,如果这两条记录的英语成绩也相同就会继续按照语文成绩进行排序,以此类推。
查询同学及总分,由高到低
注意:
- ORDER BY 子句中可以使用列别名;
- 查询数据时是先根据where子句筛选出符合条件的记录;
- 然后再将符合条件的记录作为数据源来依次执行select语句;
- 最后再通过order by子句对select语句的执行结果进行排序。
查询姓孙的同学或者姓曹的同学数学成绩,结果按数学成绩由高到低显示
此时,我们就需要结合where子句和order by子句同时进行查询了。
筛选分页结果
基本语法:
从第0条记录开始,向后筛选出n条记录:
SELECT ... FROM table_name [WHERE ..] [ORDER BY ...] LIMIT n;
从第s条记录开始,向后筛选出n条记录:
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT s, n;
从第s条记录开始,向后筛选出n条记录:
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n OFFSET s;
建议:对未知表进行查询时,最好加一条 LIMIT 1,避免因为表中数据过大,查询全表数据导致数据库卡死。
按 id 进行分页,每页 3 条记录,分别显示 第 1、2、3 页
Update
基本语法:
UPDATE table_name SET column1=expr1 [, column2=expr2] ... [WHERE ...] [ORDER BY ...] [LIMIT ...];
将孙悟空同学的数学成绩修改为80分
我们先对原数据进行查看。
然后对数据进行更新,最后查看更新后的数据。
将曹孟德同学的数学成绩变更为 60 分,语文成绩变更为 70 分
查看原数据。
然后对数据进行更新,最后查看更新后的数据。
将总成绩倒数前三的 3 位同学的数学成绩加上 30 分
先查看总成绩倒数前三的 3 位同学。
然后对数据更新完毕以后查看更新以后的结果。
将所有同学的语文成绩更新为原来的 2 倍
先查看原数据;
然后对数据进行更新以后在查看更新以后的数据。
Delete
基本语法:
DELETE FROM table_name [WHERE ...] [ORDER BY ...] [LIMIT ...]
删除数据
删除孙悟空同学的考试成绩
我们先查看原数据,然后再删除数据,删除数据完成以后查看删除结果。
删除整张表数据
在此,我们先创建一个测试表,插入一部分测试数据:
此时我们删除数据以后查看结果。
但是当我们在此插入数据以后,我们会发现自增 id 在原值上增长。
此时我们查看表结构,会有 AUTO_INCREMENT=n 项。
所以,当通过delete语句删除整表数据时,不会重置AUTO_INCREMENT=n字段,因此删除整表数据后插入数据对应的自增长id值会在原来的基础上继续增长。
截断表
基本语法:
TRUNCATE [TABLE] table_name
注意:这个操作慎用!!!
- 只能对整表操作,不能像 DELETE 一样针对部分数据操作;
- 实际上 MySQL 不对数据操作,所以比 DELETE 更快,但是TRUNCATE在删除数据的时候,并不经过真正的事物,所以无法回滚;
- 会重置 AUTO_INCREMENT 项。
首先,我们准备一个测试用表,向其中插入一些数据。
然后我们截断整表数据,然后在查看结果。
此时我们在插入数据,会发现自增是重新开始的。
此时我们查看表结构,会有 AUTO_INCREMENT=2 项。
插入查询结果
基本语法:
INSERT INTO table_name [(column [, column ...])] SELECT ...
案例:删除表中的的重复复记录,重复的数据只能有一份
首先我们创建一张表:
接下来向表中插入一些测试数据。
在这儿我们还需要创建一张空表(no_duplicate_table)结构与duplicate_table一样。然后将将duplicate_table 的去重数据插入到 no_duplicate_table。
接下来通过重命名表,实现原子的去重操作,最终查看结果可以发现已经操作成功了。
聚合函数
函数 | 说明 |
---|---|
COUNT([DISTINCT] expr) | 返回查询到的数据的 数量 |
SUM([DISTINCT] expr) | 返回查询到的数据的总和,不是数字没有意义 |
AVG([DISTINCT] expr) | 返回查询到的数据的平均值,不是数字没有意义 |
MAX([DISTINCT] expr) | 返回查询到的数据的最大值,不是数字没有意义 |
MIN([DISTINCT] expr) | 返回查询到的数据的最小值,不是数字没有意义 |
统计班级共有多少同学
使用
*
做统计,不受 NULL 影响
使用表达式做统计
这种写法相当于在查询表中数据时,自行新增了一列列名为特定表达式的列,我们就是在用count函数统计该列中有多少个数据,等价于统计表中有多少条记录。
统计班级收集的 qq 号有多少
注意,此时统计过程中NULL是不计入结果的。
统计本次考试的数学成绩分数个数
COUNT(math) 统计的是全部成绩
COUNT(DISTINCT math) 统计的是去重成绩数量
统计数学成绩总分
如果我们此时想要统计数学成绩小于60分的总分,配合where子句使用就可以了。可以看见没有结果,返回NULL;
统计平均总分
返回英语最高分
返回 > 70 分以上的数学最低分
group by子句的使用
基本语法:
select column1, column2, .. from table group by column;
案例:
- 准备工作,创建一个雇员信息表
- EMP员工表
- DEPT部门表
- SALGRADE工资等级表
员工表(emp)中包含如下字段:
- 雇员编号(empno)。
- 雇员姓名(ename)。
- 雇员职位(job)。
- 雇员领导编号(mgr)。
- 雇佣时间(hiredate)。
- 工资月薪(sal)。
- 奖金(comm)。
- 部门编号(deptno)。
部门表(dept)中包含如下字段:
- 部门编号(deptno)。
- 部门名称(dname)。
- 部门所在地点(loc)。
工资等级表(salgrade)中包含如下字段:
- 等级(grade)。
- 此等级最低工资(losal)。
- 此等级最高工资(hisal)。
进入scott数据库,在该数据库中就可以看到雇员信息表中的三张表。
其中,部门表(dept)的表结构和内容如下:
员工表(emp)的表结构和内容如下:
工资等级表(salgrade)表结构和内容如下:
显示每个部门的平均工资和最高工资
在group by子句中指明按照部门号进行分组,在select语句中使用avg函数和max函数,分别查询每个部门的平均工资和最高工资。
显示每个部门的每种岗位的平均工资和最低工资
在group by子句中指明依次按照部门号和岗位进行分组,在select语句中使用avg函数和min函数,分别查询每个部门的每种岗位的平均工资和最低工资。
注意:
- group by子句中可以指明按照多个字段进行分组,各个字段之间使用逗号隔开,分组优先级与书写顺序相同。
- 比如上述SQL中,当两条记录的部门号相同时,将会继续按照岗位进行分组。
HAVING 条件
基本语法:
SELECT ... FROM table_name [WHERE ...] [GROUP BY ...] [HAVING ...] [order by ...] [LIMIT ...];
where子句与having子句区别
- where子句放在表名后面,而having子句必须搭配group by子句使用,放在group by子句的后面。
- where子句是对整表的数据进行筛选,having子句是对分组后的数据进行筛选。
- where子句中不能使用聚合函数和别名,而having子句中可以使用聚合函数和别名。
查询数据时,SQL中各语句的执行顺序如下:
- 根据where子句筛选出符合条件的记录。
- 根据group by子句对数据进行分组。
- 将分组后的数据依次执行select语句。
- 根据having子句对分组后的数据进行进一步筛选。
- 根据order by子句对数据进行排序。
- 根据limit子句筛选若干条记录进行显示。
显示平均工资低于2000的部门和它的平均工资
- 统计各个部门的平均工资;
- having和group by配合使用,对group by结果进行过滤。
当然我们也可以使用别名的方式来进行筛选。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!