前言
前面我们介绍了对“表的属性”的操作,今天来介绍对表里面的数据的相关操作,无非就是“增删改查”。
- 增:create,关键字
insert。 - 查:read,关键字
select。 - 改:update,关键字
update。 - 删:delete,关键字
deletee。
一、create(新增)
1.1 指定列属性插入与批量插入
mysql> create table student (
-> id int primary key auto_increment,
-> name varchar(20) not null,
-> gender char(2) not null
-> );# ----------------------全列插入-----------------------------------
mysql> insert into student values (1, 'hds', '男');
# ----------------------全列插入-----------------------------------
mysql> insert into student (id, name, gender) values (2, 'zm', '女');
# ----------------------指定列属性插入------------------------------
mysql> insert into student (name, gender) values ('cg', '男');
# ----------------------批量插入多条数据----------------------------
mysql> insert into student (name, gender) values ('wl', '男'), ('swc', '男'), ...;
1.2 插入否则更新
如果一个字段为主键或唯一键,而你又插入了一个重复的字段,就会直接报错!
就可以在插入时在后面带上 on duplicate key update col1 = value, col2 = value, ...;。
+----+------+--------+ | id | name | gender | +----+------+--------+ | 1 | hds | 男 | | 2 | zm | 女 | | 3 | cg | 男 | +----+------+--------+ insert into student values (3, 'wl', '男') on duplicate key update id = 4, name = 'wl', gender = '男';
1.3 替换
replace into:根据主键或唯一键进行判断,如果相关字段不同,直接插入;否则,先删除表中重复数据,然后插入。
+----+------+--------+ | id | name | gender | +----+------+--------+ | 1 | hds | 男 | | 2 | zm | 女 | | 5 | wl | 男 | +----+------+--------+ # 主键id值重复 mysql> replace into student (id, name, gender) values (5, 'cg', '女'); +----+------+--------+ | id | name | gender | +----+------+--------+ | 1 | hds | 男 | | 2 | zm | 女 | | 5 | cg | 女 | +----+------+--------+
二、read(读取)
案例:
-- 创建表结构
create table exam_result (
id int unsigned primary key auto_increment,
name varchar(20) not null comment '同学姓名',
chinese float default 0.0 comment '语文成绩',
math float default 0.0 comment '数学成绩',
english float default 0.0 comment '英语成绩');
-- 插入测试数据
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);2.1 select 查询
(1)全列查询
select * from exam_result;
实际查询时,不建议直接全列查询,因为数据表中数据可能非常多,这样不仅不方便观察,也比较耗时。
(2)查询指定列
比如就想看一下语文成绩:
select name, chinese from exam_reult;
(3)查询字段为表达式
// 加法 select 1 + 1; // 计算总分 select name, chinese + math + english from exam_result; // 英语加10分 select name, english + 10 from exam_result;
(4)为查询结果取别名
// 给总分取别名 select name, chinese + math + english as 总分 from exam_result; // 或者 select name, chinese + math + english 总分 from exam_result; +-----------+--------+ | name | 总分 | +-----------+--------+ | 唐三藏 | 221 | | 孙悟空 | 242 | | 猪悟能 | 276 | | 曹孟德 | 233 | | 刘玄德 | 185 | | 孙权 | 221 | | 宋公明 | 170 | +-----------+--------+
(5)查询结果去重
mysql> select math from exam_result; +------+ | math | +------+ | 98 | | 78 | | 98 | | 84 | | 85 | | 73 | | 65 | +------+ mysql> select distinct math from exam_result; +------+ | math | +------+ | 98 | | 78 | | 84 | | 85 | | 73 | | 65 | +------+
2.2 where 条件
运算符:
- 比较运算符:
| 运算符 | 说明 |
|---|---|
| >、<、>=、<= | 大于,小于,大于等于,小于等于 |
| = | 等于,判断是否相等,null 不安全(null=null,结果为 null) |
| <=> | 等于,null 安全(null <=> null,结果为 true) |
| !=,<> | 不等于 |
| between a0 and a1 | 范围匹配,[a0, a1] |
| in(option, …) | 如果是 option 中任意一个,返回 true |
| is null | 为空返回 true |
| is not null | 不为空返回true |
| like | 模糊匹配,例如 x%,匹配以 x 开头的;x_ 匹配 x*。 |
- 逻辑运算符:
| 运算符 | 说明 |
|---|---|
| and | 所有条件都为 true,才为 true |
| or | 有一个为 true,即为 true |
| not | 非 |
(1)英语成绩不及格的同学及成绩
select name, english from exam_result where english < 60; +-----------+---------+ | name | english | +-----------+---------+ | 唐三藏 | 56 | | 刘玄德 | 45 | | 宋公明 | 30 | +-----------+---------+
该命令的执行过程:
from找到需要查询的表exam_result- 从
exam_result中找到满足english < 60的 - 然后
select,回显指定的列
(2)语文成绩在 [80, 90] 分的同学及成绩
// 方法一: select name, chinese from exam_result where chinese >= 80 and chinese <= 90; // 方法二: select name, chinese from exam_result where chinese between 80 and 90; +-----------+---------+ | name | chinese | +-----------+---------+ | 孙悟空 | 87 | | 猪悟能 | 88 | | 曹孟德 | 82 | +-----------+---------+
(3)数学成绩是 58 或者 98 或者 99 分的同学及数学成绩
// 方法一: select name, math from exam_result where math = 58 or math = 98 or math = 99; // 方法二: select name, math from exam_result where math in(58, 98, 99); +-----------+------+ | name | math | +-----------+------+ | 唐三藏 | 98 | | 猪悟能 | 98 | +-----------+------+
(4)姓孙的同学 及 孙某同学
// 姓孙: like '孙%' // 孙某: like '孙_' select name from exam_result where name like '孙%'; +-----------+ | name | +-----------+ | 孙悟空 | | 孙权 | +-----------+
(5)语文成绩好于英语成绩的同学
select name, chinese, english from exam_result where chinese > english;
(6)总分在 200 分以下的同学
select name, chinese + math + english from exam_result where chinese + math + english < 200; // --------------------------错误示范---------------------------- select name, chinese + math + english as 总分 from exam_result where 总分 < 200;
该 sql 执行顺序:先 from 找到表,然后直接根据 where 条件筛选。而总分是在 select 查询时才执行,即重命名是在where 执行之后,所以,语法上有问题。
(7)语文成绩 > 80 并且不姓孙的同学
// 姓孙: like '孙%' select name, chinese from exam_result where chinese > 80 and not name like '孙%'; +-----------+---------+ | name | chinese | +-----------+---------+ | 猪悟能 | 88 | | 曹孟德 | 82 | +-----------+---------+
(8)孙某同学,否则要求总成绩 > 200 并且 语文成绩 < 数学成绩 并且 英语成绩 > 80
// 孙某: like '孙_' select name from exam_result where name like '孙_' or (chinese + math + english > 200 and chinese < math and english > 80);
(9)null 的查询
mysql> select * from t; +------+------+ | id | name | +------+------+ | 1 | zm | | 2 | null | | 3 | hds | | 5 | null | +------+------+ mysql> select * from t where name is not null; mysql> select * from t where name is null;
2.3 结果排序
语法:
-- asc: 升序排列 -- desc: 降序排列 --- 默认:asc select ... from table_name [where ...] order by column [asc / desc], [...]
说明:null 值在排序时,比任何值都小!
(1)查询同学及数学成绩,按照数学成绩升序显示
select name, math from exam_result order by math asc;
(2)查询同学各门成绩,依次按 数学降序,英语升序,语文升序的方式显示
select * from exam_result order by math desc, english asc, chinese asc;
(3)查询同学及总分,由高到低
// 方法一: select name, chinese + math + english 总分 from exam_result order by chinese + math + english desc; // 方法二: select name, chinese + math + english 总分 from exam_reslut order by 总分 desc;
这里为什么可以用别名排序呢?
因为该 sql 的执行顺序为:
- 先 from 找到表 exam_result
- 然后 select 查询,并执行表达式
- 最后,排序(即此时别名就是表的列名,相当于已经有了一张name-总分的表)。
所以,mysql 的表并不只有最后显示的表,在执行 sql 的过程中表也是不断更新变化的(临时表)。
(4)查询姓孙的同学或者姓曹的同学数学成绩,结果按数学成绩由高到低显示
select name, math from exam_result where name like '孙%' or name like '曹%' order by math desc; +-----------+------+ | name | math | +-----------+------+ | 曹孟德 | 84 | | 孙悟空 | 78 | | 孙权 | 73 | +-----------+------+
该 sql 执行顺序:
- from 找到表
- 根据 where 条件筛选出一个临时表1
- 然后 select 查询指定列,形成一个临时表2
- 最后,对临时表2 根据 math 降序排列
2.4 结果分页
在进行表的查询时,如果表中的数据比较多,而我们只需要查询结果的一部分,就可以进行分页操作。
语法:
-- 从 0 开始,拿 n 条数据 select ... from t_name [where ...] [order by ...] limit n; -- 从 s 开始,拿 n 条数据 select ... from t_name [where ...] [order by ...] limit s, n; -- 从 s 开始,拿 n 条数据 select ... from t_name [where ...] [order by ...] limit n offset s;
三、update(更新)
语法:
update table_name set column = value [, column = value]
[where ...] [order by ...] [limit ...];
注意:更新数据需要谨慎,因为会覆盖原来的数据!!!
(1)将曹孟德同学的数学成绩变更为 60 分,语文成绩变更为 70 分
update exam_result set math = 60, chinese = 70 where name = '曹孟德';
(2)将总成绩倒数前三的 3 位同学的数学成绩加上 30 分
update exam_result set math = math + 30 order by chinese + math + english asc limit 3;
该 sql 执行顺序:
- update 找到表
- 然后根据总分升序排序,形成 临时表1
- 然后拿到 临时表1 的前三行形成临时表2
- 最后对 临时表2 中的所有人的数学成绩加上 30
四、delete(删除)
语法:
delete from table_name [where ...] [order by ...] [limit ...];
注意:删除表数据必须非常谨慎,不可恢复!!!
4.1 删除数据
(1)删除孙悟空的考试成绩
delete from exam_result where name = '孙悟空';
(2)删除整张表数据
delete from exam_result;
4.2 截断表
语法:truncate table_name;
mysql> create table for_truncate (
-> id int primary key auto_increment,
-> name char(8) not null
-> );
mysql> select * from for_truncate;
+----+------+
| id | name |
+----+------+
| 1 | zm |
| 2 | hds |
+----+------+
mysql> truncate for_truncate;
query ok, 0 rows affected (0.04 sec)
mysql> select * from for_truncate;
empty set (0.00 sec)
mysql> insert into for_truncate (name) values ('wl');
query ok, 1 row affected (0.01 sec)
mysql> select * from for_truncate;
+----+------+
| id | name |
+----+------+
| 1 | wl |
+----+------+那么 delete 和 truncate 有什么区别?
- truncate 后,
0 rows affected(0行被影响),即truncate实际不对数据操作,同时主键值被清空。 - delete 后,主键值延续之前。进行递增。
五、其他
5.1 聚合函数
| 函数 | 说明 |
|---|---|
| count() | 统计查询到的数量 |
| sum() | 求和,不是数字没有意义 |
| avg() | 求平均值,不是数字没有意义 |
| max() | 求最大值,不是数字没有意义 |
| min() | 求最小值,不是数字没有意义 |
- 聚合函数通常结合 group by 子句使用
- 聚合函数自动忽略 null值
(1)统计学生人数
select count(*) from exam_result; select count(1) from exam_result;
(2)统计数学总分
select sum(math) from exam_result;
(3)统计数学平均分
select avg(math) from exam_result;
5.2 group by 子句
案例:员工信息表
-- 创建表 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 '部门编号' ); -- 插入数据 insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno) values (7369, 'smith', 'clerk', 7902, '1980-12-17', 800, null, 20) ,(7499, 'allen', 'salesman', 7698, '1981-02-20', 1600, 300, 30); ,(7521, 'ward', 'salesman', 7698, '1981-02-22', 1250, 500, 30) ,(7566, 'jones', 'manager', 7839, '1981-04-02', 2975, null, 20) ,(7654, 'martin', 'salesman', 7698, '1981-09-28', 1250, 1400, 30) ,(7698, 'blake', 'manager', 7839, '1981-05-01', 2850, null, 30) ,(7782, 'clark', 'manager', 7839, '1981-06-09', 2450, null, 10) ,(7788, 'scott', 'analyst', 7566, '1987-04-19', 3000, null, 20) ,(7839, 'king', 'president', null, '1981-11-17', 5000, null, 10) ,(7844, 'turner', 'salesman', 7698,'1981-09-08', 1500, 0, 30) ,(7876, 'adams', 'clerk', 7788, '1987-05-23', 1100, null, 20) ,(7900, 'james', 'clerk', 7698, '1981-12-03', 950, null, 30) ,(7902, 'ford', 'analyst', 7566, '1981-12-03', 3000, null, 20); ,(7934, 'miller', 'clerk', 7782, '1982-01-23', 1300, null, 10);
(1)显示每个部门的平均工资和最高工资
select deptno, avg(sal), max(sal) from emp group by deptno;
(2)显示每个部门的每种岗位的平均工资和最低工资
select deptno, job, avg(sal) 平均工资, min(sal) 最低工资 from emp group by deptno, job; +--------+-----------+--------------+--------------+ | deptno | job | 平均工资 | 最低工资 | +--------+-----------+--------------+--------------+ | 10 | clerk | 1300.000000 | 1300.00 | | 10 | manager | 2450.000000 | 2450.00 | | 10 | president | 5000.000000 | 5000.00 | | 20 | analyst | 3000.000000 | 3000.00 | | 20 | clerk | 950.000000 | 800.00 | | 20 | manager | 2975.000000 | 2975.00 | | 30 | clerk | 950.000000 | 950.00 | | 30 | manager | 2850.000000 | 2850.00 | | 30 | salesman | 1400.000000 | 1250.00 | +--------+-----------+--------------+--------------+
(3)显示平均工资低于2000的部门和它的平均工资
- 统计各个部门的平均工资
select deptno, avg(sal) from emp group by deptno; +--------+-------------+ | deptno | avg(sal) | +--------+-------------+ | 10 | 2916.666667 | | 20 | 2175.000000 | | 30 | 1566.666667 | +--------+-------------+
- 结合 having 条件对 分组的结果进行筛选
select deptno, avg(sal) 平均工资 from emp group by deptno having avg(sal) < 2000; +--------+--------------+ | deptno | 平均工资 | +--------+--------------+ | 30 | 1566.666667 | +--------+--------------+
该 sql 的执行顺序:
- from: 确定并加载数据
- group by: 然后根据指定字段聚合分组,假设形成多个子表
- having:对分组后的数据进行组级别的条件筛选
- select:计算聚合函数,提取指定列,并应用列别名
5.3 插入查询结果
语法:
insert into ... select ...
在数据库内部高效完成数据的筛选、转换与批量写盘,避免将数据拉取到应用程序层再写回的开销。
应用场景:
- 数据冷热分离:将主表中不常访问的历史数据筛选出来,批量插入到归档表,随后清理主表一提升日常查询效率
- 数据备份:将满足特定条件的数据复制到临时表中作为安全备份。
六、总结
sql 标准逻辑执行顺序中,各个子句的执行顺序:
- from:确定并加载数据源(表);
- where:对表中数据进行遍历,筛选出满足条件的数据;
- group by:按照指定的字段将整表划分为不同的聚合分组;
- having:对分组后的数据进行“组级别”的条件筛选;
- select:计算所需的聚合函数,提取指定的列,并应用列别名
- distinct:去重
- order by:按照指定属性排序
- limit:对结果进行截取
mysql 中一切皆“表”!
到此这篇关于mysql对表数据的增删查改(crud)操作的文章就介绍到这了,更多相关mysql表数据增删查改内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论