- 对表中的数据操作分为4大类,增加数据,删除数据,查找数据,修改数据。
- 对表中的数据进行增删查改操作简称为CRUD。Create(增),Retrieve(查找),Updata(修改),Delete(删除)
- CRUD的操作是对表中的数据进行操作的,是SQL语句中的DML(Data Manipulation Language)数据操作语言。
Create操作
对表中新增数据,SQL语法为:
INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);
table_name
是要插入数据的表的名称。(column1, column2, column3, ...)
是要插入数据的列的列表。如果省略列名列表,则应提供值的完整列表,按照表中列的顺序插入值。VALUES
关键字后面跟着括号内的值列表,这些值按照列的顺序与列名对应。
使用案例
首先创建一张表,表中包含id
,name
,age
列。 id做为主键且自增。
- 单行数据+全列插入
单行数据的全列插入,可以省略列名列表,直接在 INSERT INTO 语句中指定 VALUES 语句。比如对上面进行全列插入
insert into user values (2,'李四',18);
- 多行数据+指定列插入
当有多行数据时,values
后面加逗号分隔符 并且在表名后面指定插入的列。 比如对上面的user表插入多行数据,指定name和age列。
insert into user(name,age) values ('王五',19),('赵六',20),('田七',29);
- 插入时更新
插入时由于主键已经存在,插入相同的值会导致插入失败。可以选择进行同步更新操作。
比如下表插入数据时,由于主键已经存在导致插入失败。
此时可以选择性的进行同步更新操作语法:
INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...)
ON DUPLICATE KEY UPDATE 列名 = value [, column = value] ...
比如对上表id为1的更新为name为周八,age为19的。
insert into user values (1,'周八',17) on duplicate key update name='周八',age=19;
- 替换
当主键和唯一键没有冲突时就直接插入。
如果主键和唯一键冲突,那么先删除在进行插入。
语法和insert一样,就是把insert换为replace。
比如上表替换周八为张三。
replace into user(id,name,age) values(1,'张三',19);
Retrieve操作
在表中查找数据,语法为
SELECT column1, column2, ...
FROM table_name
WHERE condition;
column1, column2, ...
是要检索的列名,可以是表中的任何列,也可以是表达式或聚合函数的结果。table_name
是要从中检索数据的表的名称。condition
是可选的 WHERE 子句,用于指定筛选条件,只有满足条件的行才会被检索。
使用案例
- 创建一个表用来模拟成绩表,表中包含学号,姓名,数学和计算机成绩列。
2. 向表中插入一批数据
- select全列查询
全列查询一般使用select * form 表名查询即可。 - 指定列查询
比如只查询id,name和math
select id,name,math from exam_tb;
- 查询字段为表达式
比如查询一下math和computer的成绩和
select id,name,math+cpmputer from exam_tb;
也可以将查询结果指定别名 比如将math和computer重命名为total
select id,name,math+cpmputer as total from exam_tb;
as可以省略
- 查询结果去重
使用distinct关键字进行去重
WHERE条件
在使用SELECT进行查询时,还可以使用WHERE条件进行筛选。有条件就会有比较和逻辑运算符。
MySql提供的比较运算符如下:
逻辑运算符
使用案例
先创建一个表,在表中插入一些数据。
筛选数学成绩大于80的。
筛选数学成绩在80-90的。
筛选成绩是99或者88的同学
筛选姓王的
还可以使用字段进行比较,比如筛选计算机成绩好于数学的。
使用as重命名的字段不能作为where筛选条件
null查询
与null进行比较的时候使用=
和!=
是不安全的,比较的结果是null。但是比较的结果只有真假两个结果。直接使用=
和!=
是不安全的。
使用<=>比较是安全的。但是null是0是1,也是未定义的,和0和1比较的结果都是1。
和null比较的时候推荐使用is null
和is not null
排序
对筛选的结果进行排序,排序方式有两种,分别是
- ASC 为升序(从小到大) 默认为ASC
- DESC 为降序(从大到小)
语法为:
SELECT ... FROM table_name [WHERE ...] ORDER BY column [ASC|DESC], [...];
使用示例
单段排序
筛选数学成绩大于60的,并按照升序和降序排序。
多段排序,排序优先级随书写顺序
比如数学升序,计算机降序排序
ORDER BY 中也可以使用表达式
比如总分降序排序
ORDER BY 子句中可以使用列别名
筛选分页结果
当查询一个未知表的时候,这个表可能很大,查询全表的时候容易导致数据库卡死。
这时候就需要对查询的表进行分页处理了。
语法:
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n;-- 从0开始筛选n条结果
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n offset s; --从s开始筛选n条结果
使用示例
对下标id进行分页。每页两条记录。
Update操作
对表中数据进行修改操作
语法:
UPDATE table_name SET column1=expr1 [, column2=expr2] ... [WHERE ...] [ORDER BY ...] [LIMIT ...];
一次更新一列。
一次更新多列
更新值为原值基础上变更
比如给周八同学的数学和计算机成绩加30分。
MySql不支持math+=30 这种语法。
更新全表的语句慎用!
Delete操作
删除表中的数据
语法:
DELETE FROM table_name [WHERE ...] [ORDER BY ...] [LIMIT ...];
使用示例
删除表中张三的成绩
删除整张表慎用。
截断表
截断表就是删除表中的所有数据,会删除表中的所有行,并释放表所占用的存储空间,但保留表的结构。
截断表的sql语句如下:
TRUNCATE [TABLE] table_name;
- 只能对整表操作,不能像 DELETE 一样针对部分数据操作;
- 实际上 MySQL 不对数据操作,所以比 DELETE 更快,但是TRUNCATE在删除数据的时候,并不经过真正的事务,所以无法回滚。
- 会重置
AUTO_INCREMENT
项
使用示例
截断整表数据,影响行数是 0,所以实际上没有对数据真正操作。
再次插入数据时,自增主键会重置为1。
插入查询结果
将查询的结果插入到另一个表中,
语法:
INSERT INTO table_name [(column [, column ...])] SELECT ...
使用示例
删除表中的的重复复记录,重复的数据只能有一份。
- 创建一张表,包含id和姓名。向表中插入一些重复的数据。
- 要求删除表中重复的数据。 解决思路:
- 创建一张临时表,该表的结构与测试表的结构相同。
- 以去重的方式查询测试表中的数据,并将查询结果插入到临时表中。
- 将测试表重命名为其他名字,再将临时表重命名为测试表的名字,实现原子去重操作。
创建临时表的时候,使用like用原表的结构创建临时表。
通过插入查询语句将去重查询后的结果插入到临时表中。
由于临时表和测试表的结构相同,并且select进行的是全列查询,因此在插入时不用在表名后指明column列表。
最后重命名一下两张表即可完成去重。
聚合函数
聚合函数是用于对一组数据执行计算并返回单个结果的函数。在 SQL 中,常用的聚合函数如下:
使用示例
- 准备一张测试表,插入一些数据
COUNT函数
- 使用*做统计
在select语句中使用count函数,并将*
作为参数传递给count函数,这时便能统计出表中的记录条数。
使用count(1)也能查询表中的记录条数。
这种做法就是在查询的时候给每一行都加了一个1。如下:
- 使用count函数统计列中数据个数(null 不会被统计进去)
SUM函数
向表中新加一列math,记录一下数学成绩。
更新一些成绩。
使用sum函数统计数学成绩总和
也可以使用where条件筛选,比如统计大于60分的成绩和。
AVG函数
统计平均分的。
比如统计数学的平均分。
也可以使用where条件,比如统计大于60分的平均成绩
MAX函数
统计最大数
比如统计数学成绩最高的
MIN函数
统计最小的
比如统计数学成绩最低的,
也可以使用where条件,比如统计大于60分以上的最低分。
分组查询
分组查询是指对数据库中的数据进行分组,并对每个分组进行聚合计算或筛选。在 SQL 中,可以使用 GROUP BY 子句来进行分组查询。
语法:
SELECT column1, column2, ..., aggregate_function(column),
FROM table_name
GROUP BY column1, column2, ...;
column1, column2, ...
是要进行分组的列。aggregate_function(column)
是对每个分组进行聚合计算的函数,可以是 COUNT、SUM、AVG、MIN、MAX 等聚合函数。table_name
是要从中检索数据的表的名称。
使用示例
准备雇员信息表中包含三张表,分别是员工表(emp)、部门表(dept)和工资等级表(salgrade)。
员工表(emp)中包含如下字段:
- 雇员编号(empno)。
- 雇员姓名(ename)。
- 雇员职位(job)。
- 雇员领导编号(mgr)。
- 雇佣时间(hiredate)。
- 工资月薪(sal)。
- 奖金(comm)。
- 部门编号(deptno)。
部门表(dept)中包含如下字段:
- 部门编号(deptno)。
- 部门名称(dname)。
- 部门所在地点(loc)。
工资等级表(salgrade)中包含如下字段:
- 等级(grade)。
- 此等级最低工资(losal)。
- 此等级最高工资(hisal)。
- 创建三张表
mysql> create table emp(
-> empno int(6) unsigned zerofill not null comment '员工编号',
-> ename varchar(20) default null comment '员工姓名',
-> job varchar(9) default null comment '员工职位',
-> mgr int(4) zerofill default null comment '员工领导',
-> hierdate 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 '部门编号'
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> desc emp;
+----------+--------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------------------+------+-----+---------+-------+
| empno | int(6) unsigned zerofill | NO | | NULL | |
| ename | varchar(20) | YES | | NULL | |
| job | varchar(9) | YES | | NULL | |
| mgr | int(4) unsigned zerofill | YES | | NULL | |
| hierdate | datetime | YES | | NULL | |
| sal | decimal(7,2) | YES | | NULL | |
| comm | decimal(7,2) | YES | | NULL | |
| deptno | int(2) unsigned zerofill | YES | | NULL | |
+----------+--------------------------+------+-----+---------+-------+
8 rows in set (0.00 sec)
mysql> create table salgrade(
-> grade int(11) default null comment '等级',
-> losal int(11) default null comment '最低工资',
-> hisal int(11) default null comment '最高工资'
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> create table dept(
-> deptno int(2) zerofill not null comment '部门编号',
-> dname varchar(14) default null comment '部门名称',
-> loc varchar(13) default null comment '部门所在地点'
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> desc dept;
+--------+--------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------------------+------+-----+---------+-------+
| deptno | int(2) unsigned zerofill | NO | | NULL | |
| dname | varchar(14) | YES | | NULL | |
| loc | varchar(13) | YES | | NULL | |
+--------+--------------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
- 向表中插入一些数据做测试
group by使用示例
显示每个部门的平均工资和最高工资
上述SQL会先将表中的数据按照部门号进行分组,然后各自在组内做聚合查询得到每个组的平均工资和最高工资。
- group by也可以对多个字段进行分组
比如显示每个部门的每种岗位的平均工资和最低工资
HAVING 条件
HAVING 子句用于在 GROUP BY 子句后对分组结果进行筛选。
它与 WHERE 子句的区别在于:
- WHERE 子句用于在 GROUP BY 之前对行进行筛选,而 HAVING 子句用于在 GROUP BY 之后对分组进行筛选。
- having 子句必须搭配GROUP BY使用。
- where子句中不能使用聚合函数和别名,而having子句中可以使用聚合函数和别名。
HAVING 子句的一般语法:
SELECT column1, column2, ...
FROM table_name
GROUP BY column1, column2, ...
HAVING condition;
column1, column2, ...
是用于分组的列。table_name
是要从中检索数据的表的名称。condition
是用于筛选分组结果的条件。
使用示例
显示平均工资低于2000的部门和它的平均工资
先统计各部门平均工资,在使用having筛选小于2000的。