目录
前言
开篇语
准备工作
新增数据
删除数据
修改数据
查询数据
准备表
单表查询
所有/指定字段查询
带WHERE过滤条件查询
ORDER BY排序
单行函数
多行函数
GROUP BY分组以及HAVING分组筛选
操作的必要性与相对顺序
结束语
前言
开篇语
本篇讲解MySQL的一些基础的操作——数据字段的增删改查,了解这些操作有助于我们进行前后端工作的对接。
准备工作
软件:【参考版本】Xshell7,Xftp7,Navicat Premium 16
服务器:腾讯云/阿里云
语言:Linux
版本信息:MySQL5.7,CentOS
服务器端口放通:3306
新增数据
新增语句使用的命令为insert into,分为全部字段添加和指定字段添加。
1.向全部字段中添加
insert into 表名 values(数据项1, 数据项2, 数据项3...);
这里的数据项需要和数据库表的结构一一对应,对于未指定的项设置为null,不可以不写。
使用auto_increment约束的字段也可以设置为null,比如id。
2.向指定字段中添加
insert into 表名(数据项名1, 数据项名2...) values(数据项1, 数据项2...);
如果只需要插入部分字段,可以在表名后指定需要添加的数据项名,注意前后一致。
删除数据
删除字段的命令为delete和truncate,这两个命令完整指令分别如下——
delete from 表名;
或
truncate 表名;
对于delete命令,也可以使用过滤条件where,删除指定范围的字段。
delete from 表名 过滤条件;
对于自增序列,如果使用delete命令删除,原来已经存在的序列默认保留,新的初始值会在原有的基础上增加;而truncate则不会保留原有的序列(重置自增序列)。
比如,原有序列的id为1,2,3,在delete删除后,再次添加的字段id默认将从4开始。
修改数据
又称更新字段,命令为update...set...,用于修改全部数据的指定键值。
update 表名 set 键 = 值;
当然,需要更改的数据也可以设置过滤条件,用来修改符合条件的键值。
update 表名 set 键 = 值 过滤条件;
常见的过滤条件为where,比如说我们需要修改id > 3的所有行,那么过滤条件就是——
...where id > 3;
查询数据
准备表
对于查询数据的操作,我们借助一张员工表来逐条说明。
首先,在我们的库中使用下面的代码创建一张员工表——
CREATE TABLE `emp` (
`empno` INT(4) NOT NULL COMMENT '员工编号',
`ename` VARCHAR(10) DEFAULT NULL COMMENT '员工姓名',
`job` VARCHAR(9) DEFAULT NULL COMMENT '员工岗位',
`mgr` INT(4) DEFAULT NULL COMMENT '领导编号',
`hiredate` DATE DEFAULT NULL COMMENT '入职时间',
`sal` DECIMAL(7,2) DEFAULT NULL COMMENT '工资',
`comm` DECIMAL(7,2) DEFAULT NULL COMMENT '奖金',
`deptno` INT(2) DEFAULT NULL COMMENT '部门编号',
PRIMARY KEY (`empno`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
接下来,我们向表中插入数据——
INSERT INTO emp (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES ('7369', 'SMITH', 'CLERK', '7902','1980-12-17', '800', NULL, '20');INSERT INTO emp (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES ('7499', 'ALLEN', 'SALESMAN', '7698', '1981-02-20', '1600', '300', '30');INSERT INTO emp (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES ('7521', 'WARD', 'SALESMAN', '7698', '1981-02-22', '1250', '500', '30');INSERT INTO emp (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES ('7566', 'JONES', 'MANAGER', '7839', '1981-04-02', '2975', NULL, '20');INSERT INTO emp (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES ('7654', 'MARTIN', 'SALESMAN', '7698', '1981-09-28', '1250', '1400', '30');INSERT INTO emp (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES ('7698', 'BLAKE', 'MANAGER', '7839', '1981-05-01', '2850', NULL, '30');INSERT INTO emp (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES ('7782', 'CLARK', 'MANAGER', '7839', '1981-06-09', '2450', NULL, '10');INSERT INTO emp (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES ('7788', 'SCOTT', 'ANALYST', '7566', '1987-06-13', '3000', NULL, '20');INSERT INTO emp (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES ('7839', 'KING', 'PRESIDENT', NULL, '1981-11-17', '5000', NULL, '10');INSERT INTO emp (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES ('7844', 'TURNER', 'SALESMAN', '7698', '1981-09-08', '1500', '0', '30');INSERT INTO emp (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES ('7876', 'ADAMS', 'CLERK', '7788', '1987-06-13', '1100', NULL, '20');INSERT INTO emp (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES ('7900', 'JAMES', 'CLERK', '7698', '1981-12-03', '950', NULL, '30');INSERT INTO emp (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES ('7902', 'FORD', 'ANALYST', '7566', '1981-12-03', '3000', NULL, '20');INSERT INTO emp (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES ('7934', 'MILLER', 'CLERK', '7782', '1982-01-23', '1300', NULL, '10');
单表查询
本节内容使用Navicat Premium 16查询完成,当然在Xshell中查询也是可以的,这里只是为了视觉效果更好一些。
所有/指定字段查询
1.查询emp表的所有内容
select * from emp;
*代表通配符,不可以与具体字段连用。
虽然MySQL语句对大小写不敏感,但是在实际使用过程中还是推荐使用大写。
2. 查询指定字段:编号、姓名、收入、部门号
select empno,ename,sal,deptno from emp;
3. 为查询的字段添加别名
select empno "编号",ename "姓名",sal "工资",deptno "部门号" from emp;
列名与别名之间可以加AS,也可以省略。
4.查询emp表的不重复的工作
使用distinct命令实现对指定字段数据去重,利用该命令可以查看某一字段的所有类别。
select distinct job from emp;
5.查询员工的编号,姓名,月薪,年薪(月薪*12)
select empno "编号",ename "姓名",sal "月薪",sal*12 "年薪" from emp;
6.查询员工的编号,姓名,入职时间,月薪,年薪,年收入(年薪+奖金)
由于部分员工的奖金为null,所以还需要使用ifnull()函数做处理。
select empno "编号",ename"姓名",hiredate "入职时间",sal "月薪",sal*12 "年薪",sal*12+ifnull(comm,0) "年收入" from emp;
7.拼接显示需要的字符串
使用concat命令实现指定内容的拼接,非参数部分添加引号。
SELECT CONCAT(ename,'的薪水是',sal,'美元') FROM emp;
8.显示当前的日期和时间
-- 只显示日期
SELECT CURRENT_DATE
-- 只显示时间
SELECT CURRENT_TIME
-- 显示日期和时间
SELECT CURRENT_TIMESTAMP
-- 日期和时间
SELECT NOW()
带WHERE过滤条件查询
1.查询emp表中20号部门的员工信息
对于不带分组条件的过滤条件,使用where来进行筛选。
SELECT * FROM emp WHERE deptno = 20;
2.查询姓名是SMITH的员工
字符串数据需要使用引号包裹,且对大小写不敏感。
SELECT * FROM emp WHERE ename = 'SMITH';
3.查询工资大于1500的员工
表示比较的符号——大于>、小于<、等于=、大于等于>=、小于等于<=、不等于<>或!=。
SELECT * FROM emp WHERE sal > 1500;
4.查询薪水在1300到1600之间的员工,包括1300和1600
在指定范围内,使用BETWEEN...AND...语句,过滤闭区间上数据;
排除某个范围,使用NOT BETWEEN...AND...语句,过滤两侧开区间上数据。
SELECT * FROM emp WHERE sal BETWEEN 1300 AND 1600;
5.查询20号或30号部门的员工
使用in()命令实现查询“或”功能,“非或”使用not in。
SELECT * FROM emp WHERE deptno IN (20,30);
6.查询姓名以字母S开头的员工
由于我们只知道首字母,而不知道总长度,所以使用like命令实现模糊查询(=用于精确查询)。
对于未知的部分,我们使用%代替。
比如以S开头,那么就是"S%";以S结尾,那么就是"%S";中间含有S,那么就是"%S%";以S开头,以T结尾,就是"S%T"。
SELECT * FROM emp WHERE ename LIKE "S%";
7.查询姓名为4个字符,且第二个字符为_的员工
对于已知长度的字符串,我们使用_代表一个字符。
比如,如果第二个字符为I,那么就可以用like命令查询'_I__'。
但是,这里的第二个字符为“_”,与我们的指令有所冲突,所以我们需要使用转义字符\来转义第二位。
SELECT * FROM emp WHERE ename LIKE '_\___';
8.查询佣金为null的员工
对于值为NULL的字段,不能使用=判断,需要使用is命令。
但是NULL可以参与number、date、varchar类型的运算,注意使用ifnull()转化。
SELECT * FROM emp WHERE comm IS NULL;
9.查询职位是"MANAGER"或职位不是"ANALYST"的员工
对于字符型的“或”语句,可以使用or和or not语句。
SELECT * FROM emp WHERE (job='MANAGER') OR (not(job='ANALYST'));
ORDER BY排序
1.查询员工信息(编号,姓名,月薪,年薪),按月薪升序排序
使用ORDER BY命令进行对指定分组的排序操作。
排序默认是升序排序的,也可以使用ASC命令指定升序,使用DESC命令指定降序,如果排序内容相同,则按照oracle内置的校验规则排序。
SELECT empno,ename,sal,sal*12 FROM emp ORDER BY sal ASC;
2.查询员工信息,对有佣金的员工,按佣金降序排列
这里有两步,过滤和排序,由于排序涉及到分组,而WHERE不能用于分组操作,所以WHERE需要放在GROUP BY之前。
SELECT *FROM emp WHERE comm IS NOT NULL ORDER BY comm DESC;
3.查询员工信息,按工资降序排列,相同工资的员工再按入职时间降序排列
对于多个的排序条件,使用逗号分隔,先判断靠前的条件,当靠前的条件相同时,再启动后续条件下的排序。
SELECT * FROM emp ORDER BY sal DESC,hiredate DESC;
单行函数
1.大小写转化
-- 字符串全转小写
SELECT LOWER('www.BAIdu.COM')
-- 字符串全转大写
SELECT UPPER('www.BAIdu.COM')
2.字符串拼接
select concat('hello','你好')
3.截取
substr()函数可以对指定字符串从指定位置开始截取指定长度的字符串,位置从1开始(不是从0开始哈)。
select substr('hello你好',5,3);
4.统计含有几个字节
length()函数可以统计字符串的字节数,在utf-8下中文字符占三个字节,英文占一个字节。
SELECT LENGTH('hello你好');
5.统计含有几个字符
如果需要统计的是字符的数量,则需要使用char_length()函数。
SELECT CHAR_LENGTH('hello你好');
6. 查找字符在字符串中首次出现的位置
注意,MySQL中的位置是从1开始的,如果查找不到返回0。
查找字符时,大小写不敏感。
select instr('helloworld','o');
7. 补位
可以在指定字符串的两侧补全指定字符,使之补全到需要的位数。
-- 左侧补位 #####hello
select LPAD('hello',10,'#');
-- 右侧补位 hello#####
select RPAD('hello',10,'#');
8.去除首尾空格
trim()函数可以去除开头和结尾的所有空格,但是不可以去除中间的空格。
SELECT TRIM(' he ll o ');
9.替换指定内容
replace()将所有匹配到的内容替换为指定的内容。
SELECT REPLACE('hello','l','e');
10.保留指定位数
round() / truncate()函数都可以设置保留的小数位数,但是round()是四舍五入的,truncate()是直接截断的(向下取整)。
-- 四舍五入 3.142
SELECT ROUND(3.1415,3)
-- 截断 3.141
SELECT TRUNCATE(3.1415,3)
多行函数
多行函数的内容比较少,常规的有最大值MAX()、最小值MIN()、平均值AVG()、求和SUM()以及计数COUNT()。
其中COUNT是对指定列中显示的行数的计数操作。
与单行函数的区别如下——
- 单行函数:输入一个参数,输出一个结果,例如:upper('baidu.com')->BAIDU.COM
- 多行函数:输入多个参数,或者是内部扫描多次,输出一个结果,例如:count(*)->14`
GROUP BY分组以及HAVING分组筛选
GROUP BY用于对列进行分组,对于分组操作之后的数据,就不能再使用WHERE过滤了,需要使用HAVING命令进行分组筛选。
1.显示部门编号,部门平均工资,取整数部分
GROUP BY将部门编号以同编号为一组进行分别分组,并对每一组分别求平均值。
SELECT deptno "部门编号",TRUNCATE(AVG(sal),0) "部门平均工资" FROM emp GROUP BY deptno;
2. 显示部门编号,要求部门平均工资高于2000,取整数部分
在GROUP BY确定列deptno之后,使用HAVING过滤工资均值大于2000的行。
SELECT deptno "部门编号",TRUNCATE(AVG(sal),0) "部门平均工资" FROM emp GROUP BY deptno HAVING TRUNCATE(AVG(sal),0) > 2000;
3. 降序显示部门编号,要求部门平均工资高于2000,取整数部分
排序语句在最后写。
SELECT deptno "部门编号",TRUNCATE(AVG(sal),0) "部门平均工资" FROM emp
GROUP BY deptno
HAVING TRUNCATE(AVG(sal),0) > 2000
ORDER BY 2 DESC;
4.除10号部门外,查询部门平均工资大于2000元的部门
由于平均工资需要分组分别求出,所以平均工资依然需要在GROUP BY之后筛选。
但是,对于排除10号部门,却有WHERE和HAVING两种方式。
由于WHERE在分组之前,所以可以省略对10号部门求均值的步骤,因此使用WHERE过滤方式更加节约时间。
SELECT deptno 部门, TRUNCATE(AVG(sal),0) 部门平均工资 FROM emp
WHERE deptno <> 10
GROUP BY deptno
HAVING TRUNCATE(AVG(sal),0) > 2000;
操作的必要性与相对顺序
由上面的几次筛选操作,我们可以对上面的操作进行排序——
SELECT...FROM...
WHERE...
GROUP BY...
HAVING...
ORDER BY...;
其中第一行的代码是查询的必须操作,之后的四个操作都是根据情况添加的。
WHERE和HAVING的作用都是过滤,但是二者是有差别的——
WHERE:
1)行过滤器
2)针对原始的记录
3)跟在from后面,group by之前
4)where可省
5)先执行
HAVING:
1)组过滤器
2)针对分组后的记录
3)跟在group by后面
4)having可省
5)后执行
结束语
本期内容到此结束。关于本系列的其他博客,可以查看我的MySQL专栏。
在全栈领域,博主也只不过是一个普通的萌新而已。本系列的博客主要是记录一下自己学习的一些经历,然后把自己领悟到的一些东西总结一下,分享给大家。
文章全篇的操作过程都是笔者亲自操作完成的,一些定义性的文字加入了笔者自己的很多理解在里面,所以仅供参考。如果有说的不对的地方,还请谅解。
==期待与你在下一期博客中再次相遇==
——放了挺久的【H2O2】