Bootstrap

MySQL 表的增删改查

插入

insert [into] 表名 [(列1 [, 列2] ...)] values (值1) [, (值2)...]

[ ]中为可选项,填入表的列 [(列1[,列2]...)] 可以省略表示全插入,也可以 ( ) 中指定某些列部分插入,(值1) [, (值2)...]表示可以添加多行数据,每行数据包含在 ( ) 中,行与行之间用逗号隔开。

我们先创建一张表student。

单行数据 + 全列插入

现在插入记录,插入时值的数量必须和定义表的列的数量及顺序一致。

多行数据 + 指定列插入

插入记录,插入时值的数量必须和指定列数量及顺序一致,多行数据之间用逗号隔开。

插入否则更新

由于 主键 或者 唯一键 对应的值已经存在而导致插入失败。

insert ... on duplicate key update 列1=值1, 列2=值2 ...;

insert语句如果出现冲突,则执行后面的列1=值1, 列2=值2 ...进行值替换。

例如,插入的 (101,10003,'八戒') 记录,id与孙悟空的id相同,即出现主键冲突,那么就会执行 on duplicate key update 后面的语句,将该列数据的 sn 改为 10003,name 改为 八戒。

  •  0 row affected: 表中有冲突数据,但冲突数据的值和 update 的值相等
  •  1 row affected: 表中没有冲突数据,数据被插入
  •  2 row affected: 表中有冲突数据,并且数据已经被更新
也可以使用替换语句,即如下
replace [into] 表名 [(列1 [, 列2] ...)] values (值1) [, (值2)...]
  •  主键 或者 唯一键 没有冲突,则直接插入
  •  主键 或者 唯一键 如果冲突,则删除后再插入

replace 语句结构与 insert 语句结构一致,只是把 insert 改为 replace。

例如,插入的 (100,10000,'观音菩萨') 记录,id与唐僧的id相同,sn与唐僧的sn相同,即出现主键冲突和唯一键冲突,那么就会删除原数据,插入新数据。这里由于出现主键冲突和唯一键冲突的都是同一列,所以只删除一列,如果出现主键冲突和唯一键冲突的在不同列,那么就会删除两列数据

查询

我们先创建一个考试成绩表格并插入数据

insert into exam_result (name, chinese, math, english) values
('小明', 67, 98, 56),
('小红', 87, 78, 77),
('小翠', 88, 98, 90),
('小朱', 82, 84, 67),
('小雨', 55, 85, 45),
('小鑫', 70, 73, 78),
('小彤', 75, 65, 30),
('小朵', NULL, NULL, NULL);
select 表达式1, 表达式2 ... from 表名;

此处的表达式含义非常广,它可以是列名,通配符*,计算式等。

全列查询
指定列查询
表达式为计算式
例如,我们将chinese,math,english加起来就可以得到总分成绩
为查询结果指定别名
select 表达式1 [as] 别名1, 表达式2 [as] 别名2 ... from 表名;

[ ]中的as表示as可以省略。

例如,我们可以将chinese,math,english加起来就可以得到的总分成绩重新命名为total

distinct 结果去重

我们查看数学成绩时发现有两列98,如果我们只想查看一列98,即对查询结果去重,那么我们可以在所查询的列前面加 distinct 即可。

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)

示例:

1. 英语不及格的同学及英语成绩 ( < 60 )
select name,english from exam_result where english<60;

2.文成绩在 [80, 90] 分的同学及语文成绩

select name,chinese from exam_result where chinese between 80 and 90;

3.数学成绩是 58 或者 59 或者 98 或者 99 分的同学及数学成绩
使用 or   进行条件连接
select name,math from exam_result where math=58 or math=59
or math=98 or math=99;

  使用 in   条件
select name,math from exam_result where math in(58,59,98,99);

4.名字中含明的同学
select name from exam_result where name like '%明';

5.总分在 200 分以下的同学
select name,chinese+math+english total from exam_result where 
chinese+math+english<200;

虽然前面已经将chinese+math+english重命名为了total,但是where条件不能写为total<200

查询时报错了,找不到total这个列,这与语句的执行顺序有关。

其执行顺序为:

  1. 确定要查询的表,执行from exam_result
  2. 确定要查询的条件,执行where total<200
  3. 确定查询的列,执行select name,chinese+math+english total

因为where的执行顺序在确定查询的列之前,所以在查询的列上给chinese+math+english起别名total,where语句并不知道。

order by 结果排序

select ... from 表名 where ... order by 列1 [asc|desc], 列2 [asc|desc] ... ;

asc表示升序,desc表示降序,如果不指定那么默认为asc升序。

1.同学及数学成绩,按数学成绩升序显示

select name,math from exam_result order by math asc;

SQL中认为NULL比所有值都小,所以NULL被放在了第一列。

2.查询同学及总分,由高到低
select name,chinese+math+english total from exam_result order by chinese+math+english desc;

使用order by时能不能直接用别名total呢?

我们发现使用order by时可以使用别名total,这是因为order by是在整个表查询 select name, chinese+math+english total结束后执行完毕,得到了所有符合条件的结果之后order by才进行排序。

其执行顺序为:

  1. 确定要查询的表,执行from exam_result
  2. 确定要查询的条件,执行where...
  3. 确定查询的列,执行select name,chinese+math+english total
  4. 对查询结果进行排序,执行order by total desc

limit 筛选分页结果

-- 从 0 开始,筛选 n 条结果
select 表达式 from 表名 [where ...] [order by ...] limit n;

-- 从 s 开始,筛选 n 条结果
select 表达式 from 表名 [where ...] [order by ...] limit s, n;

-- 从 s 开始,筛选 n 条结果,比第二种用法更明确,建议使用
select 表达式 from 表名 [where ...] [order by ...] limit n offset s;
1.按 id 进行分页,每页 3 条记录,分别显示 第 1 2 3

更新

update 表名 set 列1 = 值1, 列2 = 值2 [where ...] [order by ...] [limit ...]
1.将小明的语文和英语成绩都变更为  60

2.将总成绩倒数前三的 3 位同学的数学成绩加上 30

删除

delete

delete from 表名 [where ...] [order by ...] [limit ...];

我们先将整张表的数据都删除掉,并且执行select时查询不到任何数据,说明确实删除成功了。执行show create table exam_result\G时,发现auto_increment=9,说明delete是不会清空自增长的。

之后我们再次插入数据。

insert into exam_result (name, chinese, math, english) values
('小明', 67, 98, 56),
('小红', 87, 78, 77),
('小翠', 88, 98, 90),
('小朱', 82, 84, 67),
('小雨', 55, 85, 45),
('小鑫', 70, 73, 78),
('小彤', 75, 65, 30),
('小朵', NULL, NULL, NULL);

我们执行select * from exam_result 命令时发现 id 就从9开始自增了。

truncate

两者对比

TRUNCATE

  • 适用于快速清空表中的所有数据,尤其是在数据量较大时,因为它直接释放数据页,执行速度快,但只能删除整张表,不能像 DELETE 一样针对部分数据操作
  • 不支持条件删除,不能用于有外键约束的表,且操作不可回滚。
  • 会重置 AUTO_INCREMENT

DELETE

  • 适用于根据特定条件删除数据,支持事务和回滚,适合删除少量数据或需要条件判断的场景。
  • 执行速度较慢,因为它是逐行删除并记录日志。
  • 不会重置 AUTO_INCREMENT

聚合函数

函数说明
count([DISTINCT] expr)返回查询到的数据的数量
sum([DISTINCT] expr)
返回查询到的数据的总和,不是数字没有意义
avg([DISTINCT] expr)
返回查询到的数据的平均值,不是数字没有意义
max([DISTINCT] expr)
返回查询到的数据的最大值,不是数字没有意义
min([DISTINCT] expr)
返回查询到的数据的最小值,不是数字没有意义

1.统计班级共有多少同学

2.统计数学成绩总分
3.统计平均总分
4.返回 > 70 分以上的数学最低分

分组

group by 子句的使用
select 表达式 from 表名 [where ...] [order by ...] [limit ...] group by 列名;

创建 employees 表

create table employees (
    employee_id int auto_increment primary key,
    department varchar(50),
    salary decimal(10, 2)
);

-- 插入一些示例数据
insert into employees (department, salary) values
('Sales', 45000),
('Sales', 55000),
('Marketing', 50000),
('Marketing', 60000),
('Engineering', 58000),
('Engineering', 62000);

查询每个部门的平均工资

select department,avg(salary) from employees group by department;

;