MySQL之基本查询(下)-表的增删查改

**表的增删查改:**CRUD : Create(创建), Retrieve(读取),Update(更新),Delete(删除)

Update(更新)

语法:

UPDATE table_name SET column = expr [, column = expr ...] [WHERE ...] [ORDER BY ...] [LIMIT ...]

列值更新

案例

更新值为具体值
原先的值 将孙悟空同学的数学成绩变更为 80 分

mysql> update exam_result set math=80;//这个语句是将所有人的数学成绩变为80

mysql> update exam_result set math=80 where name='孙悟空';//进行where条件筛选

一次更新多个列

将曹孟德同学的数学成绩变更为 60 分,语文成绩变更为 70 分

mysql> update exam_result set math=60 ,chinese=70 where name='曹孟德';

更新值为原值基础上变更

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

数据更新,不支持 math += 30 这种语法

原本排名

update exam_result set math=math+30 order by chinese+math+english limit 3;

执行后变化了


将所有同学的语文成绩更新为原来的 2 倍

**注意:更新全表的语句慎用!**没有 WHERE 子句,则更新全表

mysql> update exam_result set chinese=chinese*2;

set左侧是列名右侧是表达式或者常数 ;

Delete(删除)

删除数据

语法:DELETE FROM table_name [WHERE ...] [ORDER BY ...] [LIMIT ...]
删除孙悟空同学的考试成绩

查看原数据:mysql> select * from exam_result where name='孙悟空';

删除数据:mysql> delete from exam_result where name='孙悟空';

查看删除结果:mysql> select * from exam_result where name='孙悟空';
删除总分最低的人

查看原数据最低的人:mysql> select name,chinese+math+english total from exam_result order by total limit 1;

删除操作:mysql> delete from exam_result order by chinese+math+english limit 1;
查看删除操作:宋公明不存在了

删除整张表数据

注意:删除整表操作要慎用!在MySQL中分为表和表里面的数据;

delete语句重点是删除表里的数据;表结构不受影响

delete删除表数据

准备测试表:mysql> CREATE TABLE for_delete (

-> id INT PRIMARY KEY AUTO_INCREMENT,

-> name VARCHAR(20)

-> );

插入测试数据:mysql> INSERT INTO for_delete (name) VALUES ('A'), ('B'), ('C');


查看测试数据:mysql> SELECT * FROM for_delete;


查看表结构:mysql> show create table for_delete\G

可以看到有auto_increment(可以理解为计数器),有专门的维护他

**删除整表数据:**DELETE FROM for_delete;


查看表结构:发现还是计数器值还是从4开始,并不会因为清除数据我的auto_increment清零
**再插入一条数据:**INSERT INTO for_delete (name) VALUES ('D');

查看数据发现自增 id 在原值上增长:

截断表

语法:TRUNCATE [TABLE] table_name

注意:这个操作慎用

  1. 只能对整表操作,不能像DELETE一样针对部分数据操作

  2. 实际上MySQL不对数据操作,所以比DELETE更快 ,但是TRUNCATE在删除数据的时候,并不经过真正的事物,所以无法回滚

  3. 会重置AUTO_INCREMENT项

测试表:mysql> CREATE TABLE for_truncate (

-> id INT PRIMARY KEY AUTO_INCREMENT,

-> name VARCHAR(20)

-> );
插入测试数据:mysql> INSERT INTO for_truncate (name) VALUES ('A'), ('B'), ('C');
查看测试数据:mysql> SELECT * FROM for_truncate;


查看表结构:mysql> show create table for_truncate\G

计数器的值是在4开始

截断整表数据:mysql> truncate for_truncate;

注意影响行数是 0,所以实际上没有对数据真正操作

查看删除结果:mysql> SELECT * FROM for_truncate;
表还在:只是数据没了
再次查看表结构:mysql> show create table for_truncate\G

发现计数器值清空了

再插入一条数据:mysql> INSERT INTO for_truncate (name) VALUES ('D');
再次查看表结构:发现id在重新增长
查看数据:mysql> SELECT * FROM for_truncate;

插入查询结果

语法:INSERT INTO table_name [(column [, column ...])] SELECT ...

案例:删除表中的的重复复记录,重复的数据只能有一份

创建原数据表:CREATE TABLE duplicate_table (id int, name varchar(20));

插入测试数据:INSERT INTO duplicate_table VALUES (100, 'aaa'), (100, 'aaa'), (200, 'bbb'), (200, 'bbb'), (200, 'bbb'), (300, 'ccc');

去重:mysql> select distinct * from duplicate_table;

这步操作只是显示出去重后的数据,对原始表的数据没有影响

思路:

创建一个结构一样的空表,然后将原来的表的去重数据放到新表里,再重命名两个表;

创新表:mysql> create table no_duplicate_table like duplicate_table;

你也可以重新create结构;不过用like方便因为是结构相似的表;新表插入数据mysql> insert into no_duplicate_table select distinct * from duplicate_table;


重命名mysql> rename table duplicate_table to old_duplicate_table,no_duplicate_table to duplicate_table;
/var/lib/mysql 是 Linux 系统中 MySQL 数据库默认的数据存储目录 。可以到配置文件cd /var/lib/mysql 中找到文件,在cd你所用的数据库可以看到你所建的表;

在MySQL中你建立一个数据库就是相当于建立一个文件夹,创一个表就是创立一个文件;

最后rename防止其他文件关联使用,如果最开始rename可能其他文件无法使用了因为没有原来的了。

聚合函数

MySQL中也有自己的函数

count:

统计班级共有多少同学:mysql> select count(*) from exam_result;

使用 * 做统计,不受 NULL 影响
支持重命名mysql> select count(*) 总数 from exam_result;

使用count(1),count(2)结果一样的 ;因为你的表有多少行我就显示多少行,类似于select 1 from exam_result;你有5行那我就显示5行的1;那count(1)就是几行
统计本次考试的数学成绩分数个数:mysql> select count(math) 总数 from exam_result;

对成绩做去重distinct放count前没有用,因为我count已经聚合了是一个整数,再怎么去重我还是整数不变

错误:mysql> select distinct count(math) 总数 from exam_result;


正确:mysql> select count(distinct math) 总数 from exam_result;


sum:

**统计数学成绩总分:**mysql> select sum( math) 总数 from exam_result;


AVG:

统计平均总分:****mysql> select avg( math+chinese+english) 总数 from exam_result;
返回数学平均分:mysql> select avg( math) 总数 from exam_result;

也可以这样:mysql> select sum( math)/count(1) 总数 from exam_result;

**返回数学成绩不及格的人数:**mysql> select count(1) from exam_result where math<60;


**英语不及格的人的总分:**mysql> select sum(english) from exam_result where english<60;

所有不及格的人总分为101
max

**返回英语最高分:**mysql> select max(english) from exam_result;

错误:mysql> select name,max(english) from exam_result;不允许这样操作


min

**返回>70分以上的数学最低分:**mysql> select min(math) from exam_result where math>70;

group by子句的使用

在select中使用group by子句可以对指定列进行分组查询

语法:select column1, column2, .. from table group by column;

分组的目的是进行分组后,方便进行聚合统计

准备工作,创建一个雇员信息表(来自oracle 9i的经典测试表)

将表上传到linux中

将表导入到我们的数据库里:mysql> source /home/wwz/scott_data.sql;

可以看到成功导入并且数据库中有了scoot库;

使用当前数据库:mysql> use scott;
查表:mysql> show tables;成功导入表

emp员工表 dept部门表 salgrade工资等级表




显示员工平均工资和最高工资:mysql> select avg(sal),max(sal) from emp;


**按照部门显示平均工资和最高工资:**mysql> select avg(sal),max(sal) from emp group by deptno;
**显示每个部门的平均工资和最高工资:**mysql> select deptno,avg(sal),max(sal) from emp group by deptno;
分组是指定列名(group by table_name)表示分组列是它,实际分组是使用这一列不同行的数据进行聚合统计分组(把这一列的一组分为多个组,进行组内统计)

**显示每个部门的每种岗位的平均工资和最低工资:**mysql> select avg(sal),min(sal),job, deptno from emp group by deptno, job;//用逗号来隔离不同分组条件

先按照部门分组再按照工作分组(将表分为部门组表,再将每个部门组表分为工作表,最后聚合统计;相当于一个树向下分支再分支)

显示平均工资低于2000的部门和它的平均工资

1. 统计各个部门的平均工资

mysql> select avg(sal) from emp group by deptno;

2. 对group by结果进行过滤

mysql> select avg(sal),deptno from emp group by deptno having avg(sal)<2000;

having的作用是你分完组了也聚合完了我再根据聚合统计的结果刷选;

having经常和group by搭配使用,作用是对分组进行筛选,作用有些像where。

先执行 select avg(sal),deptno from emp group by deptno后执行having avg(sal)<2000;
mysql> select max(mgr),avg(sal),min(sal),job, deptno from emp where ename!='SMITH' group by deptno, job having avg(sal)<2000;

where是对具体的任意列进行条件筛选;

having是对我们分组聚合之后的结果进行条件刷选;

他们俩的应用场景是不同的,如果他俩在一块,先where后having;

执行顺序:1.告诉我你从那个表里拿数据from emp 2.告诉我拿数据的筛选条件是什么 where ename!='SMITH' 3. 按照对应的组进行分组 group by deptno, job 4. 按照分组后的进行聚合统计以及重命名 5. 进行结果having筛选
注意的是from左边的列必须在from右边分组出现,否则不成功

比如:mysql> select ename,avg(sal),min(sal),job, deptno from emp group by deptno, job;//ename不属于分组条件所以无法分组

错误:ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'scott.emp.ename' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

错误:select mgr,avg(sal),min(sal),job, deptno from emp group by deptno, job;

正确:select max(mgr),avg(sal),min(sal),job, deptno from emp group by deptno, job;
所以只有在分组条件中出现的列才能在select后面,或者直接聚合函数也行
不要单纯的认为只有磁盘上表结构导入到MySQL,真实存在的表才叫表;

中间筛选出来的包括最终结果,可以理解为逻辑上的表!--"MySQL中一切皆表 ";

只要能对单表处理好CURD,那么所有的sql场景,都能用统一的方式进行;

相关推荐
苹果醋31 小时前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
了一li1 小时前
Qt中的QProcess与Boost.Interprocess:实现多进程编程
服务器·数据库·qt
码农君莫笑2 小时前
信管通低代码信息管理系统应用平台
linux·数据库·windows·低代码·c#·.net·visual studio
别致的影分身2 小时前
使用C语言连接MySQL
数据库·mysql
过过过呀Glik2 小时前
在 Ubuntu 上安装 MySQL 的详细指南
mysql·ubuntu
京东零售技术4 小时前
“慢”增长时代的企业数据体系建设:超越数据中台
数据库
sdaxue.com4 小时前
帝国CMS:如何去掉帝国CMS登录界面的认证码登录
数据库·github·网站·帝国cms·认证码
o(╥﹏╥)5 小时前
linux(ubuntu )卡死怎么强制重启
linux·数据库·ubuntu·系统安全
阿里嘎多学长5 小时前
docker怎么部署高斯数据库
运维·数据库·docker·容器
Yuan_o_5 小时前
Linux 基本使用和程序部署
java·linux·运维·服务器·数据库·后端