MySQL 的增删改查
MySQL 的增删改查
1. CRUD
- 注释:在SQL中可以使用“--空格+描述”来表示注释说明
- CRUD 即增加(Create)、查询(Retrieve)、更新(Update)、删除(Delete)四个单词的首字母缩写。
create table student(id int,name varchar(20));
1.1 新增
语法:
insert [into] table_name [column] values(values_list);
这里 into 可加可不加
column 是表中属性 这里后面会说
values_list 这里是 按照表属性的顺序来添加数据
1.1.1 单行添加
insert into student values(1,"张三");
这里可以用中文 是因为 在创建数据表的时候用了 utf8;
这的 字符串 可以用 单引号 也可用双引号
1.1.2 指定列插入
insert into student (id) values (2);
这里的意思是 添加一个 id为 2的数据 其余为默认值 null
1.1.3 多行插入
insert into student values(3,"李四"),(4,"王五");
这里有一个要注意的点
多行插入的效率比 单行插入要高
datatime 类型如何填入?
可以用一个固定的字符串来表示日期
insert into student values(1,'张三','2000-01-01 12:00:00');
表示现在的时间可以直接用 函数 now();
insert into student values(2,'李四',now());
1.2 查询 (select)
select 条件查询的执行顺序
- 遍历表中每个记录
- 把当前值带入条件,根据条件进行筛选
- 如果合格记录条件成立,就要保留,进行列上的表达式计算
1.2.1 全列查询
语法:select*from + 要查询的表
select*from exam_result;
把表中所有的行和列 全部展示出来
*表示通配符 表示所有列
危险操作:
- 读取硬盘,把硬盘的 IO 跑慢了, 此时程序的其他部分像访问就 非常慢
- 操作网络,也可能把网卡跑满,此时其他客户端想通过网络访问服务器 也非常慢
1.2.2 指定列查询
select id,name,birthday from exam_result;
1.2.3 查询字段为表达式
select name,english-10 from exam_result;
注意 这个并不会改变我们的原始数据 只是在最终响应里做了计算
进行查询的时候,是把服务器这里的数据提取迟来,返回客户端,并且以 临时表的形式进行展示
所以 这里只是修改了 临时表
可以计算每个同学的总成绩
select name,chinese+english+math from exam_result;
查询时可以进行简单的统计操作
1.2.4 查询的时候 指定别名(给表也可以) (as)
select 表达式 as 别名 from 表名;
1.2.5 去重(distinct)
select distinct 列名 from 表名;
效率很低
1.2.6 排序(order by)
select 列名,列名 from 表名 order by 列名 asc/desc;
asc 为升序
desc 为降序
默认 asc
这里 前面的列名 是 返回临时表中展现的 后面的 列名 是 依靠这个列来排序的意思
- 没有 order by 字句的查询 ,返回的顺序是未定义,永远不要依赖这个数据
- null 数据排序 视为比任何值小,升序时出现在最上面
- null 跟 任何数 相加 还是 null
加入 上面的别名 (注意顺序)
select name,chinese+math+english as total from exam_result order by total desc;
对多个字段进行排序 这里的意思是这样的
优先数学降序 然后如果数学成绩相同 则看英语成绩升序排序
select name,chinese,english,math from exam_result order by math desc,english, chinese desc;
1.2.7 条件查询 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) |
这里注意
- null 默认为 false
- where 条件可以使用表达式,但不能用别名
- and的优先级高于or 这边不建议记 如果需要优先进行可以直接用 ();
-
基本查询
select name,chinese from exam_result where chinese > 80; select name,chinese+math+english 总分 from exam_result where chinese+math+english < 200;
这里 where 后面的 chinese+math+english 不可以写成总分
-
and 与 or
select * from exam_result where chinese > 80 and english < 70; select * from exam_result where chinese > 80 or english < 70;
-
between ... and ...
select name,english,chinese from exam_result where chinese between 80 and 90;
-
in
select name,chinese from exam_result where chinese in (98,87,82,88);
-
模糊查询like
通配符 % 匹配多个字符 (包括0)
select name from exam_result where name like '孙%';// 孙悟空 孙权
孙% 查询开头为 孙的
%孙 查询 结尾为孙的
%孙% 查询包含孙的
通配符 _ 匹配一个字符
select name from exam_result where name like '孙_';// 孙权 select name from exam_result where name like '孙__';// 孙悟空
-
Null 的查询 这里要注意
select * from exam_result where chinese = null;
我们使用 = 查询null 即使有 null 也会显示 没有
因为 在 mySQL 中 null 默认为 false
当他 查询到 null 会被认为是 空 然后 空又默认为 false 所以咧 无法查询到结果
这里就要使用:
select * from exam_result where chinese <=> null;//可以看到多个列 select * from exam_result where chinese is null;//只能看到一个列 select * from exam_result where chinese <=> english;
1.2.8 分页查询 limit
语法:
select * from exam_result limit 3;
select * from exam_result limit 3 offset 3;
查询 开头三行数据
offset 的意思是 偏移量
1.3 修改(update)
语法
update 表名 set 列名 = 值 where 条件;
模拟面试题 掌握
如果不写条件 就全修改
Rows matched: 7 Changed: 7 Warnings: 1
Rows matched:参与改变的行数
Changed:被改变的行数
Warnings:错误 show warnings
这里可以用这行代码看 错误点在哪里
-- 将孙悟空同学的数学成绩变更为 80 分
update exam_result set chinese = 80 where name = "孙悟空";
-- 将曹孟德同学的数学成绩变更为 60 分,语文成绩变更为 70 分
update exam_result set math = 60,chinese = 70 where name = "曹孟德";
-- 将总成绩倒数前三的 3 位同学的数学成绩加上 30 分
update exam_result set math = math + 30 order by chinese+english+math limit 3;
-- 将所有同学的语文成绩更新为原来的 2 倍
update exam_result set chinese = chinese*2;
1.4 删除(delete)
语法
delete from 表名 where / order by / limit ;
案例:
delete from exam_result where name = "孙悟空";
-- 删除这个表数据
delete from exam_result;
delete 跟 drop 不一样
delete 是 删除表内数据 但是不删除表
drop 整个表删除
2. 数据库约束
数据库中的数据 是有一定约束的
有些数据认为是合法数据有些是非法数据
数据库,自动的对数据的合法性进行晓燕检查的一系列机制
目的 保证数据库中能够避免被插入/修改一些非法数据
MySQL 中提供了 以下约束:
- not null :指示某列不能存储 Null 值
- unique:保证某列的每行必须是唯一的值
- default:规定没有给列赋值时的默认值
- primary key:not null 和 unique 的结合
- foreign key: 外键约束
2.1 not null
create table if not exists student(id int not null,name varchar(20));
创建表时 指定 列 不可以为空
2.2 unique
指定列必须是唯一值 不可以重复的
每次使用这个约束都会先进行查询操作
create table if not exists student(id int unique);
2.3 default
给指定列 赋默认值
create table if not exists student(name varchar(20) default "未命名");
2.4 primary key
设置 主键 即为 不重复 以及不能为空
这里注意 一个表中 只有一个主键 ,但是 主键不一定是一个列 可以多个列 组成一个主键
create table if not exists student(id int primary key);
数据库 有一个 自增 让数据库 自己去分配
对于整数类型的主键,常配搭自增长auto_increment来使用。 插入数据对应字段不给值时,使用最大值+1。
create table if not exists student(id int primary key auto_increment,name varchar(20));
2.5 foreign key
外键约束:
语法:
foreign key (字段名) references 主表(列);
案例:
先建一个 class 表
create table class(
id int primary key,
name varchar(20),
);
再建一个 student 表 与其产生外键约束
create table student(
id int primary key,
name varchar(20),
classId int,
foreign key classId references class(id),
);
这里 student 的 classId 与 class中的 id 产生了外键约束
class 为 父表
student 为 子表
特性:
- 父表约束子表
classId 只能 是 id中的其中一个 也就是 引用了 id 中的值
如果 id 中没有这个值 就会报错
-
子表反向约束父表
如果 classId中 已经引用了 id 中的某一个值
那么这个值在父表中不可以被修改或者删除
同样 如果 子表跟父表已经产生了 外键约束的关系
即便 两个表都是空表 在 子表还在的情况下 无法直接删除父表
-
父表中必须有主键/unique 否则无法构成外键约束
3.表设计
-
一对一
比如让你设计两个 一对一的表
用户 以及 身份证
一个用户对应一个身份证号
如何设计
我们可以设计一个 person 表 以及 identity 表
create table person(id int primary key,name varchar(20)); create table identity(id int,name varchar(20),password int, foreign key id references person(id));
让 他们之间 有一个属性互相关联 即可
-
一对多
比如
一个班级有多个学生
一个学生只有一个班级
class -----> student
create table class( classId int primary key, name varchar(20) ); create table student( id int primary key, name varchar(20), classid int, foreign key classid references class(classid) );
让 每个学生 去对应班级
其实也可以 用另外一种 就是让
班级中存放每个学生的 id
但是 mySql 中没有 数组这种基础结构 所以 mySQL 不适用
-
多对多
一个学生可以选多种课
一个课程中有多个学生
create table student( studentId int primary key, name varchar(20); ); create table course( courseId int primary key; name varchar(20); ); create table student_coutse( studentId int; courseId int; );
这里写了一个连接表 比如
student 中 有 (1,张三)(2,李四)
course 中 有 (1,语文) (2,数学)
这里 的 连接表 student_course
就可以这样存 (1,1)(1,2)
代表 张三选了 语文课 张三选了数学课
4.新增增强
插入 查询的结果
这里有一个必要的前提条件 就是你想要插入的 和查询的必须 列数一样 不然胡报错
insert into test(name,email) select name,email from student;
5.查询
5.1 聚合查询
5.1.1 聚合查询
一些 mySQL 提供的 聚合函数
函数 | 说明 |
---|---|
count() | 返回查询到的数据的 数量 |
sum() | 返回查询到的数据的 总和,不是数字没有意义 |
avg() | 返回查询到的数据的 平均值,不是数字没有意义 |
max() | 返回查询到的数据的 最大值,不是数字没有意义 |
min() | 返回查询到的数据的 最小值,不是数字没有意义 |
-
count()
-- 查询 student 的 所有行数 select count(*) from student; -- 查询 student 中 name 的行数 select count(name) from student;
说明:
这里的 通配符 * 是会将 null 也一起计算的
但是 name 就不会
同样的 这里的括号内也是可以 添加表达式 像上面一样
-
sum()
select sum(chinese) from exam_result;
说明:
查看 chinese 的总和
同样也是可以 加入表达式的
select sum(chinese+english+math) from exam_result;
这里会新建一个临时表计算 chinese+english+math 然后再进行输出
注意
字符串的运算 他不会报错 它会将 字符串 转换为 double 结构进行运算 如果无法转换则会变成0 并且产生一个 错误
select sum(name) from exam_result;
7 warnings
-
avg()
-
max()
-
min()
5.1.2 group by语句
分组 按照字段进行分组
语法:
select name,role,min(salary),max(salary),avg(salary) from emp group by role;
可以衔接 where 语句
-
查询每个岗位的平均工资 但是排除张三的
先排除 后计算
直接使用 where where 语句一般在 group by 前面
select name,rolo,avg(salary) from emp where name != "张三" group by role;
-
查询每个岗位的平均工资 但是排除平均工资大于2w的结果
算计算后排除
使用 having 语句,having语句一般在 group by 后面
select name,role,avg(salary) from emp group by role having avg(salary) < 20000;
-
同时完成以上的两种 查询
查询每个岗位的平均薪资 不算张三 平且排除 大于2w 的结果
select name,avg(salary) from emp where name != "张三" group by role having avg(salary) < 20000;
5.2 联合查询
可以用 ,克制使用 ,不能非常广泛的使用
多个表进行同时查询
关键思路:
理解 ”笛卡尔积“ 工作过程
-
进行笛卡尔积
select * from student join score;
-
筛选条件
select * from student join score where student.id = score.student_id;
-
精简列
select sn,name,score from student join score where student.id = score.student_id;
-
聚合
select sn,name,sum(score) from student join score where student.id = score.student_id group by name;
5.3 子查询
嵌套查询 两个 sql 用 一个sql 完成
-
单行 子查询
我想 查询不想毕业同学的 同班同学
-- 先查询 不想毕业同学 的班级号 select classes_id from student where name = "不想毕业"; -- 再使用 班级号 来查询其他同学 select id,name from student where classes_id = 1;
子查询 就是 将上面 合二为一 进行嵌套
select id,name from student where classes_id =(select classes_id from student where name = "不想毕业");
5.4 合并查询
使用合并查询 前后查询的结果之中 必须保证字段一致
-
union
查询id小于3 或者名字为英文的
取两个结果集的 并集
-- 可以利用 or select * from course where id<3 or name = "英文"; -- 利用 union select * from course where id < 3 union select * from course where name = "英文";
or 跟 union 的区别
union 的逻辑是 将两个临时表进行合并 然后去重
or 则是 进行遍历
而且 union 可以进行 不同表之间的 合并查询
or 只能 针对单个表
-
union all
合并后不进行去重操作 取得两个结果的并集
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了