MySQL练习与小结
当你专注一件事的时候,时间总是过得很快!
- foreign key 练习
-- 切换数据库 use stumgr -- 删除班级表 drop table t_class1 -- 创建一个班级表 create table t_class1 ( cno int auto_increment not null, cname varchar (12) not null, room int (4), primary key (cno) ); -- 查看班级表 desc t_class1 -- 添加班级数据 insert into t_class1 values (null,'Javay1班',501),(null,'Javay2班',502),(null,'大数据1班',401); -- 查看班级表信息 select * from t_class1 -- 清空班级表数据 truncate table t_class1 -- 删除学生表 drop table t_student1 -- 创建学生表 create table t_student1 ( sno int primary key auto_increment, name varchar (20), sex char (1) default '男', age int, classno int, constraint fk_t_student1_classno foreign key (classno) references t_class1 (cno) ); -- 查看学生表 desc t_student1 -- 添加学生表数据 insert into t_student1 values (null,'张三','男',22,1); insert into t_student1 values (null,'李思','女',23,3); insert into t_student1 values (null,'王武','男',22,3); insert into t_student1 (name,age,classno) values ('赵六',21,2),('孙琦',21,1); -- 查看学生表数据 select * from t_student1 -- 清空学生表数据 truncate t_student1
- 单行函数练习
-- 单行函数 select * from emp select lower(ename) from emp select upper(ename) from emp select ename from emp select ename,lower(ename) from emp select ename,lower(ename),upper(ename) from emp select ename,lower(upper(ename)) from emp -- 使用函数并没有更改数据库中的数据值,只是简化了查询的代码量 select sal from emp select min(sal),max(sal),sum(sal),avg(sal),count(sal) from emp -- 函数的分类 -- 单行函数 即对(多行)每一条记录进行操作,分别产生一条记录 -- lower(ename)、upper(name) -- 多行函数 对(多行)每一条记录进行操作,结果只产生一条记录 -- max(sal)、min(sal)、sum(sal)、avg(sal)、count(sal) -- 区分单行函数和多行函数 -- 方法1、按照定义区分 -- 方法2、除了多行函数(常用的有5个),都是单行函数 -- 字符函数 select * from emp where length(ename) = 6 select ename from emp where length(ename) = 6 select ename,sal from emp where length(ename) = 6 select ename,lower(ename),upper(ename) from emp select empno,ename,job,substring(ename,1,3) subname from emp -- 截取字符串 从第一位到第三位 显示职员信息(工号,姓名,岗位) select empno,ename,job,replace(job,"CLERK",'店员') from emp where job = 'clerk' select empno,ename,job,replace(job,'MANAGER','经理') from emp where job = "MANAGER" select job from emp where job = 'manager' -- select job where job = 'manager' from emp -- 错误的写法 select empno,ename,job,replace(job,"MANAGER","经理") from emp where job = 'manager' select empno,ename,job,replace(job,'manager',"经理") from emp where job = "MANAGER" -- replace()括号中的职位名必须和表格中一样,不然显示不出后面的汉字 -- 数值函数 select abs(-5), -- 取绝对值 ceil(3.2), -- 向上取整 floor(3.2), -- 向下取整 round(3.4), round(3.5), -- 四舍五入 mod(10,3), mod(10,5), -- 取模 相当于取余 pi(), -- 圆周率 sqrt(25), -- 开平方 pow(2,5), pow(5,2) -- 幂运算 select rand(),rand(),rand() -- 返回0~1之间的随机数 select truncate(3.1415926,3) -- truncate(num,n)返回num舍弃小数点后第n位后的数值 -- 日期函数 select now(),sysdate(),sleep(3),sysdate(),now() select now(),curdate(),curtime() -- 流程函数 select ename,deptno,sal,if(sal >= 3000,"high","low") from emp select ename,deptno,sal,if(sal >= 3000,'高收入层','低收入层') from emp order by sal select ename,deptno,job,sal*12+comm year_income from emp -- 算上补贴的年收入,补贴(comm)为null无法算出年收入 select ename,deptno,job,sal*12+ifnull(comm,0) year_income from emp -- 加上ifnull(comm,0)可以把补贴为null的置为0,从而得出年收入 -- ifnull(comm,0) 即 if comm is null then comm = 0 select nullif(1,1),nullif(1,2),nullif(2,1),nullif(2,2) -- if 1 == 2 then null else 1 select ename,deptno,sal,case when sal >= 3000 then '高收入' else "低收入" end sal_level from emp select ename,deptno,sal, case when sal >= 3000 then 'high' else case when sal >= 2000 then 'mid' else 'low' end end from emp -- 其他函数 select database(),user(),version(),password('zhangsan'),inet_aton('192.168.10.1'),inet_ntoa(3232238081) -- mysql 提供了一个名为dual的虚拟表 默认的from dual是可以省略的
- 单表查询练习
-- where 子句练习 select * from emp -- 先查看下员工表信息 select * from emp where empno = 7566 -- 查询工号为7566的职员信息 select * from emp where sal > 3000 -- 查看薪水大于3000的职员信息 select * from emp where job = 'MANAGER' select * from emp where JOB = 'manager' -- mysql 中默认不去分大小写 -- 加上区分大小写的条件 即在查询的字段名前加上binary select * from emp where binary job = 'manager' select * from emp where job != 'manager' select * from emp where job > 'manager' -- 字符串也可以大于小于 select * from emp where job <> "manager" select * from emp where hiredate < '1981-12-23' -- and 逻辑运算符 select * from emp select * from emp where sal <= 3000 and sal >= 1200 select * from emp where sal between 1200 and 3000 -- between 表示的意思是闭区间 select * from emp where sal not between 3000 and 1200 select * from emp where sal <= 3000 && sal >= 1200 -- &&等同于and -- or 逻辑运算符 select * from emp where deptno = 30 or 10 -- 不能这样表述 select * from emp where deptno = 30 or deptno = 10 -- 查询部门编号为30或10的 select * from emp where deptno = 30 || deptno = 10 -- ||等同于or select * from emp where deptno in (30,10) select * from emp where deptno in (10,30) -- 模糊匹配 -- 姓名中带K的 %代表任意多个字符 select * from emp select * from emp where ename = '%K%' -- 不能使用等号 而是要用单词 like select * from emp where ename like '%k%' -- K 不区分大小写 -- 加上binary就是区分大小写 select * from emp where binary ename like '%K%' select * from emp where binary ename like '%k%' select * from emp where binary ename not like '%k%' select * from emp where binary ename not like '%K%' -- 姓名的第二个字母是L _单个下划线代表任意一个字符 第几个字符要加几个_ select * from emp where ename like '__m%' -- 名字中第二个字母是m的职员信息 select * from emp where ename like '_M%' -- 名字中第一个字母是m的职员信息 select * from emp where binary ename like '_m%' -- 区分大小写 名字中第一字母是小写m的职员信息 select * from emp where binary ename like '_M%' -- 名字中第一个字母是大写M的职员信息 -- is null select * from emp where comm = 0 -- 不是is null的用法 select * from emp where comm is null -- 查看comm是null的职员信息,comm是null和comm = 0 代表的含义是不同的 select * from emp where comm is not null -- is 后加 not 是正确的用法 not加在is前不符合语法要求 -- select * from emp where comm not is null select * from emp where comm != 0 -- 不包括comm为null的数据 -- 小括号 优先级高 select * from emp where job = 'salesman' or "CLERK" and sal >= 1280 -- and运算符的优先级比or高 不包括工资大于1280的clerk select * from emp where (job = "salesman" or job = "clerk") and sal >= 1280 select * from emp where job = 'SALESMAN' or (job = 'CLERK' and sal >1280)
- 表单查询多行函数
-- 多行函数 select max(sal),min(sal),sum(sal),count(sal),avg(sal) from emp select max(comm),min(comm),sum(comm),avg(comm),count(comm) from emp select * from emp select max(ename),min(ename),sum(ename),avg(ename),count(ename) from emp -- 统计有几个员工 select empno,count(1) from emp select count(comm) from emp -- 不能通过领补贴的人来统计 -- 统计有几个部门 select deptno from dept select count(distinct deptno) from emp -- 部门40并未出现在emp表中,所以此语句输出的部门个数是3 select count(deptno) from dept -- 对任意一张表,统计有几条记录 select count(*) from emp select count(*) from dept select empno from emp -- 可以通过主键统计 select 1 from emp select count(1) from emp -- 统计表的记录个数建议用此方法,比count(*)效率高 -- 统计有几个岗位 select count(distinct job) from emp -- 多行函数会自动排除null值 -- max(),min(),count()适用于所有数据类型 -- sum()avg()仅限于数值类型(整点 浮点) -- 多行函数会更多地用在分组查询中 group by
- 多表查询练习
-- SQL99多表连接查询 -- 查询员工的编号、姓名和部门编号 select * from emp select empno,ename,deptno from emp -- 查询员工的编号、姓名和部门编号、部门的名称 -- 交叉连接 使用关键字join select * from dept select * from emp select * from emp cross join dept select * from dept cross join emp -- 左和右的区别 左连接 右连接 -- 自然连接 select * from emp natural join dept -- 使用关键字natural 会自动按照所有的同名列进行匹配,并且同名列只显示一次 -- 优点是:简单 select empno,ename,deptno,dname from emp natural join dept -- 缺点:没有指定各字段属于哪个表,执行时需要进行判断,效率低 -- 解决:给各个字段指定表的名字 select emp.empno,emp.ename,deptno,dept.dname -- 自然连接中同名列不能使用表名前缀 from emp natural join dept -- 缺点:表名如果很长,字段多的时候,SQL语句就会显得复杂 -- 解决:使用别名 select e.empno,e.ename,deptno,d.dname from emp e natural join dept d -- using 子句 -- 自然连接的缺点:会自动按照“所有的”同名列进行匹配,如果希望按照某一个同名列进行匹配,自然连接无能为力 -- 解决:使用using子句 select * from emp e join dept d using(deptno) -- e.deptno = d.deptno select e.empno,e.ename,deptno,d.dname from emp e join dept d using(deptno) -- on子句 -- natural、using的缺点:都必须有同名列 -- 连接查询要求两个表必须由关联(比如emp的deptno和dept的deptno),但是不要同名 -- 如果有关联,但是不同名,该怎么解决? select empno,ename,d.deptno,d.dname -- 关联列必须使用前缀 from emp e join dept d on(e.deptno = d.deptno) -- 此处e和d的deptno碰巧同名了 -- 查询员工的编号、姓名、部门编号、部门的名称,要求薪水大于2000 select empno,ename,d.deptno,d.dname from emp e join dept d on(e.deptno = d.deptno) where sal > 2000 -- 小结: -- 实际开发中尽量使用on子句,不管是否有同名列,都可以使用;虽然稍显复杂,但是可读性高 -- SQL99连接查询的优点:连接条件和筛选条件是分开的 -- 连接条件:on(e.deptno = d.deptno) using(deptno) natural cross -- 筛选条件:where sal > 2000 -- SQL92中,连接条件和筛选条件是没有分开的
- 外连接查询
-- SQL99外连接查询 select * from dept select * from emp update emp set deptno = null where empno = 7788; -- 把scott员工设置成没有部门 select * from emp e join dept d on(e.deptno = d.deptno) -- 返回13条记录,缺少了没有部门的员工scott,缺少了没有员工的部门40;只显示匹配的数据 -- 左外连接 select * from emp e left join dept d on(e.deptno = d.deptno) -- 右外连接 select * from emp e right join dept d on(e.deptno = d.deptno) -- 全外连接 select * from emp e full join dept d on(e.deptno = d.deptno) -- mysql中没有全外连接 -- 曲线救国 select * from emp e left join dept d on(e.deptno = d.deptno) union -- 使用union关键字可以曲线实现全外连接 select * from emp e right join dept d on(e.deptno = d.deptno)
- group by having练习
-- 统计各部门的平均工资(只显示平均工资2000以上的) select deptno,avg(sal) from emp group by deptno having avg(sal) > 2000 order by avg(sal) select avg(sal) from emp -- 这是所有部门的平均工资 select deptno from emp select deptno,avg(sal) from emp -- 字段不能和分组函数共存,除非该字段是分组group by字段 select deptno,avg(sal) from emp group by deptno select deptno,avg(sal) from emp -- where avg(sal) > 2000 -- where 子句不能使用多行函数(分组函数) group by deptno having avg(sal) >2000 -- 各个子句的书写是有顺序的 order by avg(sal) desc -- 统计各个岗位的平均工资,除了manager select distinct job from emp select job,avg(sal) from emp group by job having job != 'MANAGER' order by avg(sal) select job,avg(sal) from emp group by job having job != 'MANAGER' && job != 'PRESIDENT' order by avg(sal) -- where 子句不能使用多行函数(分组函数) select job,avg(sal),count(1) from emp where count(1) > 3 group by JOB -- 如果没有group by子句,select列表中不允许出现字段(单行函数)与多行函数混用的情况 -- 出现在select列表中的字段,如果不是包含在多行函数中,那么该字段必须同时在group by子句中出现 -- 不允许在where子句中使用多行函数 -- 小结 -- where子句和having子句的联系和区别 -- 联系 -- 都是筛选记录 -- 区别 -- ◆where是group by之前,having是group by之后 -- ◆where中不能出现在多行函数,having中可以出现多行函数 -- select语句总结 -- ◆select语法格式 -- ◆select column,group_function(column) -- ◆from table -- ◆[where condition] -- ◆[group by group_by_expression] -- ◆[having group_condition] -- ◆[order by column] -- ◆select语句执行顺序 -- ◆from--->where--->group by--->select-having--->order by
- group by having加强练习
-- 列出工资最小值小于2000的职位 select job,min(sal) from emp group by job having min(sal) < 2000 order by min(sal) -- 获取各个职位的最小工资 select job,min(sal) from emp group by job having min(sal) order by min(sal) desc -- 按最小工资降序排列 -- 获取各个职位的最小工资,筛选出小于2000的 select job,min(sal) from emp group by job having min(sal) < 2000 -- 列出平局工资大于1200元的部门和工作搭配组合 select * from emp select * from dept select distinct deptno from emp select distinct job from emp select distinct job,deptno from emp select deptno,job,avg(sal),count(1) from emp group by deptno,job having avg(sal) > 1200 order by avg(sal) desc -- 统计人数小于4的部门的平均工资 select deptno,avg(sal),count(1) from emp group by deptno having count(1) < 4 -- 统计各部门的最高工资,排除最高工资小于3000的部门 select deptno,max(sal) from emp group by deptno having max(sal) >= 3000 order by max(sal)
一休哥~~~
Develop good habits and use them to cover up bad habits.