一,MYSQL入门
1.数据库相关概念
DB:数据库:存储数据的仓库,保存了一系列有组织的数据。DBMS:数据库管理系统:数据库是通过DBMS创建和操作的容器。SQL:结构化查询语言:专门用来与数据库通信的语言。
2.数据库的好处
1.可以持久化数据到本地2.可以实现结构化查询,方便管理
3.数据库存储数据特点
1.将数据放到表中,表放到库中。2.一个数据库有多张表,每个表都有一个名字,用来标识自己。表名具有唯一性。3.表具有一些特性,这些特性定义了数据在表中如何存储,类似Java中类的设计。4.表有列组成,我们也称为字段。所有表都是由一个列或多个列组成的,每一列类似Java中的属性。5.表中的数据按照行来存储,每一行类似于Java中的对象。
4.mysql的安装与使用
参照mysql安装文档
5.Mysql常用命令
显示数据库----->show Databases;使用数据库----->use 数据库名;显示表---->show tables;显式指定数据库的表---->show tables from 数据库名;查看位于那个数据库---->select database();显示表结构--->desc 表名;查看数据库版本:--->select version();查看数据库版本2:----->Dos:mysql --version;查看数据库信息----->show CREATE DATABASE mydb1;查看服务器中的数据库,并把mydb1的字符集修改为utf-8----->ALTER DATABASE mydb1character set utf8;删除数据库----->drop database mydb1;表中增加一栏信息----->alter table student add image blob;删除表----->drop table student;修改地址----->alter table student modify address varchar(100);删除一个属性-----> alter table student drop image;修改表名----->rename table student to students;查看表的创建细节----->show create table students;修改表的字符集为 gbk----->alter table students character set gbk;列名name修改为studentname----->alter table students change name studentname varchar(100);
6.mysql语法规范
1.不区分大小写,建议关键字大写,表名列名小写。2.每条命令最好用分号结尾。3.每条语句可以缩进,换行。4.注释单行注释:#注释文字-- 注释文字多行注释:/* */
二,DQL查询语言
1.基础查询
**语法: select 查询列表 from 表名****查询列表:表中的字段,常量,表达式,函数****查询的结果是张虚拟的表格**1.查询表中的单个字段select last_name from employee;2.查询表中的多个字段select last_name,salary,email from employee;3.查询表中的所有字段select * from employee;4.查询常量值select 100;select 'john';5.查询表达式select 100*98;6.查询函数select version();7.起别名select last_name as name from employee;select last_name name from employee;8.去重查询员工表中涉及到的所有的部门编号select distinct department_id from employee;9.+的作用#运算符:两个操作数都为数值型,则做加法运算;#其中一方为字符型,试图将字符型数值转换成数值型,#如果转换成功,继续做加法运算;否则,将字符型数值#转换为0;10.使用concat实现连接#案例:查询员工名和性连接成一个字段SELECT CONCAT(username,PASSWORD) FROM USER;#任何数与null做运算结果都为null
2.条件查询
语法:
select 查询列表 from 表名 where 筛选条件
分类:
①按照条件表达式筛选
条件运算符:>,<,=,!=,>=,<=
查询员工工资>1w2的员工信息select * from employee where salary >12000;查询部门编号!=90号的员工名和部门编号select name, dep_id from employee where dep_id 1=90;
②按照逻辑表达式筛选
逻辑运算符:&&,||,!,AND,OR,NOT
查询工资在一万到两万之见的员工名,工资以及奖金。select name,salary ,jiangjin where salary between 10000 and 20000;查询部门编号不在90-110之间,或者工资高于15000的员工信息。select * from employee where department<90||department>110 ||salary >15000;
③模糊查询
like:一般和通配符搭配使用
通配符:
%任意多个字符,包含0个字符
_任意单个字符
BETWEEN AND:包含临界值
IN:判断某个字段的值是否属于in列表中的某一项
IS NULL,IS NOT NULL:=或者!=不能用来判断null
安全等于<=>可以判断null
查询员工名中包含a的员工信息select * from emp where name like %a%;查询员工名中第三个字符为e第五个字符为a的员工名和工资select name ,salary from emp where name like %__e_a%;员工名中第二个字符为_的员工名select name from emp where name like %_\_%;查询员工编号在100到120之间的所有员工信息select * from emp where id between 100 and 120;查询员工的工种编号是IT_PRIG,AD_PRES,AD_VP中的一个员工名和工种编号;select name , id from emp where id in(IT_PRIG,AD_PRES,AD_VP);查询没有奖金的员工名和奖金率select salary , jjl from emp where salary is Null;查询有奖金的员工名和奖金率select salary ,jjl from emp where salary is not null;
④IF null的使用:
查询员工号为176的员工的姓名和部门号和年薪SELECT last_name ,department_id , salary*(1+IFNULL(commission_pct,0))*12 '年薪'FROM employees WHERE employee_id =176;
3.排序查询
语法:
select 查询列表
from 表
where 筛选条件
order by 排序列表 asc 或desc (升序或者降序,默认为升序)
查询员工信息,要求工资从高到低排序select * from emp order by salary desc;查询部门编号大于等于90的员工信息,按照入职时间先后排序select * from emp where dep_id >=90 order by createtime asc;按照员工年薪的高低显示员工的信息和年薪select * ,年薪 from emp order by salary*(1+if null(jjl,0))*12 as 年薪 desc;按姓名长度显示员工的姓名和工资select name ,salary from emp order by length(name) asc;查询员工信息,先按照工资排序,再按照员工编号排序select * from emp order by salary asc,id asc;
4.常见函数
功能:类似Java中的方法
分类:单行函数
分组函数
1.单行函数
1.字符函数
1.length 获取参数值的字节个数select * from emp order by length(name);2.concat 拼接字符串select concat(last_name,first_name) as 姓名 from emp;3.upper,lower 大小写转换函数案例:将姓变大写,名字变小写,然后拼接SELECTCONCAT(UPPER(last_name),LOWER(first_name))FROM employees;4.substr,SUBSTRING 截取字符串SELECT SUBSTR('李莫愁',2);SELECT SUBSTR('李莫愁',2,3);案例:姓名中首字符大写,其他的小写然后用_拼接显示出来SELECTCONCAT(UPPER(SUBSTR(last_name, 1, 1)),'_',LOWER(SUBSTR(last_name, 2))) outputFROMemployees ;5.instr:返回字串第一次出现的索引,如果找不到返回0SELECT INSTR('风急天高猿啸哀','天') AS out_put;6.trim :去掉前后空格或前后指定字符SELECT LENGTH(TRIM(' 张三丰 ')) AS out_put;SELECT TRIM('a' FROM 'aaaa1aa2aaa3aaa') AS out_put;7.lpad :用指定字符填满指定长度(左填充)SELECT LPAD('苍老师',10,'*');8.rpad:用指定字符填满指定长度(右填充)SELECT RPAD('苍老师',10,'*');9.replace 替换SELECT REPLACE('千锋培训机构','千锋','尚硅谷');
2.数学函数
1.round:四舍五入SELECT ROUND(1.666);SELECT ROUND(1.567,2);2.ceil 向上取整SELECT CEIL(1.52);3.floor 向下取整SELECT FLOOR(1.52);4.truncate:截断(小数点后保留几位)SELECT TRUNCATE(1.65,2);5.mod:取余SELECT MOD(10,3);
3.日期函数
1.now:返回当前系统日期时间SELECT NOW();2.curdate:返回当前系统日期SELECT CURDATE();3.curtime:返回当前时间SELECT CURTIME();4.获取指定部分的年月日时分秒SELECT YEAR(NOW());SELECT YEAR(hiredate) FROM employees;5.str_to_date将字符通过指定的格式转化成日期SELECT STR_TO_DATE('1998-3-2','%Y-%c-%d') AS out_put;案例:查询入职时间为1992-4-3的员工信息SELECT * FROM employeesWHERE hiredate=STR_TO_DATE('2016-3-3','%Y-%c-%d');6.date_format 将日期转换成字符SELECT DATE_FORMAT(NOW(),'%y年%m月%d日') AS 日期;案例:查询有奖金的员工名和入职日期(xx月/xx日 xx年)SELECTlast_name,DATE_FORMAT(hiredate, '%c月/%d日 %y')FROMemployeesWHERE commission_pct IS NOT NULL ;
4.其他函数
SELECT VERSION();SELECT DATABASE();SELECT USER();
5.流程控制函数
1.if:IF else效果SELECT IF(10>5,'true','false');案例:查询如果有奖金就备注有,没有就备注没有。SELECTlast_name,commission_pct,IF(commission_pct IS NULL,'没奖金','有奖金') AS 备注FROMemployees ;2.case函数1)switch-CASE语法:CASE 要判断的字段或者表达式WHEN 常量1 THEN 要显示的值1或者语句1WHEN 常量2 THEN 要显示的值2或者语句2...ELSE 要显示的值n或者语句n;案例:查询员工的工资,要求部门号==30,显示的工资为1.1倍,部门号==40,显示的工资为1.2倍,部门号==50,显示的工资为1.3倍,其他部门,显示原有工资。SELECTsalary AS 原始工资,department_id ,CASEdepartment_idWHEN 30THEN salary * 1.1WHEN 40THEN salary * 1.2WHEN 50THEN salary * 1.3ELSE salaryEND AS 新工资FROMemployees ;2)CASE 使用2:语法:CASEWHEN 条件1 THEN 要显示的值1或语句1WHEN 条件2 THEN 要显示的值2或语句2...ELSE 要显示的值n或语句nEND案例:查询员工的工资情况如果>2w,显示A如果>1.5w,显示B如果>1w,显示C否则,显示DSELECTsalary,CASEWHEN salary > 20000THEN 'A'WHEN salary > 15000THEN 'B'WHEN salary > 10000THEN 'C'ELSE 'D'END AS 工资等级 FROM employees ;
2.分组函数
功能:用作统计使用
1.sum :求和SELECT SUM(salary) FROM employees;2.avg:平均值SELECT AVG(salary) FROM employees;3.max:最大值SELECT MAX(salary) FROM employees;4.min:最小值SELECT MIN(salary) FROM employees;5.count:计算个数SELECT COUNT(salary) FROM employees;总结①.sum,avg一般用于处理数值类型②.max,min,count用来处理任何类型③.以上分组函数都忽略null值④.可以和distinct搭配SELECT SUM(DISTINCT salary) 纯净,SUM(salary) FROM employees;6.count的详细介绍①select COUNT(*) FROM employees;②select COUNT(1) FROM employees;③和分组函数一同查询的字段要求是group by后的字段。
5.分组查询
GROUP BY 和分组函数对应
分组查询中分组条件分为两类
| 数据源 | 位置 | 关键字 | |
|---|---|---|---|
| 分组前筛选 | 原始表 | GROUP BY 子句的前面 | WHERE |
| 分组后筛选 | 分组后的结果集 | GROUP BY 子句的后面 | HAVING |
分组函数做条件肯定是放在having子句中。
group BY 子句支持单个字段分组,多个字段分组
(多个字段之间用逗号隔开没有顺序要求),表达式或函数。
也可以添加排序,放在整个分组查询的最后。
案例:查询每个工种的最高工资SELECTMAX(salary),job_idFROMemployeesGROUP BY job_idORDER BY MAX(salary) ASC ;案例:查询邮箱中包含a字符的,每个部门的平均工资SELECTAVG(salary),department_idFROMemployeesWHERE email LIKE '%a%'GROUP BY department_id ;#select Avg(salary),dep_id from employee where email like %a% group by dep_id ;案例:查询有奖金的每个领导手下员工的最高工资SELECTMAX(salary),manager_idFROMemployeesWHERE commission_pct IS NOT NULLGROUP BY manager_id ;#select max(salary) ,manage_id from employees where commission_pct is not null group by manager_id;案例:哪个部门的员工个数大于二?SELECTCOUNT(*),department_idFROMemployeesGROUP BY department_idHAVING COUNT(*) > 2 ;#select dep_id from emp group by dep_id having count(*)>2;案例:查询每个工种有奖金的员工的最高工资>12000的工种编号和最高工资SELECTMAX(salary),job_idFROMemployeesWHERE commission_pct IS NOT NULLGROUP BY job_idHAVING MAX(salary) > 12000 ;#select job_id ,max(salary) from emp where commission_pct IS NOT NULL group by job_id having max(salary)>12000;案例:查询领导编号>102的每个领导手下的最低工资>5000的领导编号是哪个?SELECT manager_id ,MIN(salary)FROM employeesWHERE manager_id>102GROUP BY manager_idHAVING MIN(salary)>5000;#select manager_id from emp where manager_id>102 group by manager_id having min(salary)>5000;#按照员工姓名的长度分组,查询每一组的员工个数,筛选员工个数>5的有哪些?SELECT COUNT(*) AS cFROM employeesGROUP BY LENGTH(last_name)HAVING c>5;# select count(*) from emp group by length(name) having count(*)>5;#查询每个部门每个工种的员工的平均工资SELECT AVG(salary),job_idFROM employeesGROUP BY department_id,job_id;#select avg(salary) from emp group by dep_id,job_id;#查询每个部门每个工种的员工的平均工资并且按照平均工资的高低显示SELECT AVG(salary),job_idFROM employeesGROUP BY department_id,job_idORDER BY AVG(salary) ASC;#select avg(salary) from emp group by dep_id,job_id order by avg(salary) asc;
6.连接查询
又称为多表查询,当查询的字段来自多个表时,就会用到连接查询。
笛卡尔乘积现象:表1有m行,表2有n行,结果:mn行
发生原因:没有有效的连接条件**
分类
①按年代分类
sql92:仅仅支持内连接
sql99:不支持全外连接
②按功能分类
| 内连接 | 外连接 | 交叉连接 |
|---|---|---|
| 等值连接 | 左外连接 | |
| 非等值连接 | 右外连接 | |
| 自连接 | 全外连接 |
1.等值连接
①多表等值连接的结果为多表的交集部分
②n表连接,至少需要n-1个连接条件
③多表的顺序没有要求
④一般需要为表起别名
⑤可以搭配前面介绍的所有子句使用,比如排序,分组,筛选
#案例一:查询女优名对应的男优名SELECTNAME,boyNameFROMbeauty,boysWHERE beauty.boyfriend_id = boys.`id` ;#select name, boyname from girl ,boy where girl.boyfriend_id=boy.id;#案例:查询员工名和对应的部门名SELECTlast_name,department_nameFROMemployees,departmentsWHERE employees.`department_id` = departments.`department_id` ;#select name ,dep_name from emp e,dep d where e.dep.id= d.id;#案例:查询员工名,工种号,工种名。SELECTlast_name,emp.`job_id`,job_titleFROMemployees emp,jobs jobWHERE emp.`job_id` = job.`job_id` ;#select name , e.job_id,job_title from emp e,job j where e.job_id=j.id;#案例:查询有奖金的员工名和部门名SELECTlast_name,department_nameFROMemployees emp,departments depWHERE commission_pct IS NOT NULL && emp.`department_id` = dep.`department_id` ;#select name ,dep_name from emp e ,dep d where e.dep_id =d.id &&e.salary_pct is not null;#案例:查询城市名第二个字符为o的部门SELECTdepartment_nameFROMlocations l,departments dWHERE l.`location_id` = d.`location_id`AND l.`city` LIKE '_o%' ;#select dep_name from location l , dep d where l.city like %_o% && l.id =d.location_id;#案例:查询每个城市的部门个数SELECTCOUNT(*),cityFROMlocations l,departments dWHERE l.`location_id` = d.`location_id`GROUP BY l.`city` ;#select count(*),city from loca l,dep d where l.loc_id=d.loc_id group by count(*) asc;#案例:查询有奖金的每个部门的部门名和部门的领导编号和该部门的最低工资SELECTd.`department_name`,d.manager_id,MIN(salary)FROMemployees e,departments dWHERE e.`department_id` = d.`department_id`AND e.`commission_pct` IS NOT NULLGROUP BY d.`department_id`,d.`department_name` ;#select dep_name ,d.manager_id ,min(salary) from emp e ,dep d where e.`department_id` = d.`department_id` AND e.`commission_pct` IS NOT NULL GROUP BY d.`department_id`,d.`department_name` ;#案例:查询每个工种的工种名和员工的个数,并且按照员工个数降序排序SELECTj.job_title,COUNT(*)FROMjobs j,employees eWHERE j.`job_id` = e.`job_id`GROUP BY e.`job_id`,j.`job_title`ORDER BY COUNT(*) DESC ;#案例:查询员工名,部门名和所在城市SELECTlast_name,department_name,cityFROMemployees e,departments d,locations lWHERE e.`department_id` = d.`department_id`AND d.`location_id` = l.`location_id` ;
2.非等值连接
#案例:查询员工的工资和工资级别SELECT DISTINCTsalary,grade_levelFROMemployees e,job_grades jWHERE e.salary >= j.lowest_sal && e.salary <= j.highest_salORDER BY salary ASC ;
3.自连接
#案例:查询员工名和上级的名称SELECTe.last_name,m.last_nameFROMemployees e,employees mWHERE e.manager_id = m.employee_id ;
4.内连接
INNER 可以省略
#查询员工名,部门名SELECTlast_name,department_nameFROMemployees eINNER JOIN departments dON e.department_id = d.department_id ;#查询名字中包含e的员工名和工种名SELECTlast_name,job_titleFROMemployees eINNER JOIN jobs jON e.job_id = j.job_idWHERE last_name LIKE '%e%' ;#查询部门个数>3的城市名和部门个数SELECTcity,COUNT(*)FROMdepartments dINNER JOIN locations lON d.`location_id` = l.`location_id`GROUP BY cityHAVING COUNT(*) > 3 ;#查询哪个部门的部门员工个数>3的部门名和员工个数,并按照个数降序排序SELECTdepartment_name,COUNT(*)FROMemployees eINNER JOIN departments dON e.`department_id` = d.`department_id`GROUP BY e.department_idHAVING COUNT(*) > 3ORDER BY COUNT(*) DESC ;#查询员工名,部门名,工种名,并按照部门名降序排序SELECTlast_name,department_name,job_titleFROMemployees eINNER JOIN departments dON e.`department_id` = d.`department_id`INNER JOIN jobs jON e.`job_id` = j.`job_id`ORDER BY department_name DESC ;#查询员工工资级别SELECTgrade_level,salaryFROMjob_grades jINNER JOIN employees eON e.`salary` BETWEEN j.`lowest_sal`AND j.`highest_sal` ;#查询每个工资级别的个数,并且降序排序SELECT grade_level,COUNT(*)FROM employees eINNER JOIN job_grades jON e.`salary` BETWEEN j.`lowest_sal`AND j.`highest_sal`GROUP BY grade_levelORDER BY COUNT(*) DESC;#查询员工的名字和上级的名字SELECT e1.last_name, e2.last_nameFROM employees e1INNER JOIN employees e2ON e1.`employee_id`=e2.`manager_id`;
5.左外连接
语法:
SELECT 查询列表
FROM 表1 【连接类型】
JOIN 表2
ON 连接条件
WHERE 筛选条件
GROUP BY 分组
HAVING 筛选条件
ORDER BY 排序条件
连接类型:
内连接:inner
左外连接:left
右外连接:right
全外连接:full
交叉连接:cross
外连接
用于查询一个表中有,另一个表中没有的数据
左外连接,left左边是主表
右外连接,right右边是主表
Mysql不支持全外连接
#没有男朋友的女生SELECTg.`name`,b.`boyName`FROM beauty gLEFT JOIN boys bON g.`boyfriend_id`=b.`id`WHERE b.`boyName` IS NULL;
6.交叉连接
笛卡尔乘积
7.子查询
出现在其它语句中的select语句,称为子查询或内查询
外部的查询语句,称为主查询或外查询
分类:
①按照子查询出现的位置:
| select后面 | from后面 | where或having后面 | exists后面 |
|---|---|---|---|
| 仅仅支持标量子查询 | 支持表子查询 | 标量子查询,列子查询 | 表子查询 |
②按照结果集的行列数不同:
| 标量子查询 | 列子查询 | 行子查询 | 表子查询 |
|---|---|---|---|
| 结果只有一行一列 | 结果一列多行 | 一行多列 | 多行多列 |
1)where或having后面
特点:
子查询一般放在小括号内
子查询一般放在条件的右边
标量子查询,一般搭配着单行操作符
列子查询:一般搭配多行操作符使用
1.标量子查询#谁的工资比Abel高SELECTlast_nameFROMemployeesWHERE salary >(SELECTsalaryFROMemployeesWHERE last_name = 'Abel') ;#返回job_id于141号员工相同,salary比143号员工多的员工 姓名,job_id和工资SELECTlast_name,job_id,salaryFROMemployeesWHERE job_id =(SELECTjob_idFROMemployeesWHERE employee_id = 141)AND salary >(SELECTsalaryFROMemployeesWHERE employee_id = 143)#返回公司工资工资最少的员工的姓名,job_id,salarySELECTlast_name,job_id,salaryFROMemployeesWHERE salary =(SELECTMIN(salary)FROMemployees);#查询最低工资大于50号部门最低工资的部门id和其最低工资SELECTdepartment_id,MIN(salary)FROMemployeesGROUP BY department_idHAVING MIN(salary) >(SELECTMIN(salary)FROMemployeesWHERE department_id = 50) ;2.列子查询多行操作符:IN / NOT in:等于列表中的任意一个ANY / SOME :和子查询返回的某一个值比较ALL :和子查询返回的所有值比较#返回location_id是1400或者1700的部门中的所有员工姓名SELECTlast_nameFROMemployeesWHERE department_id IN(SELECT DISTINCTdepartment_idFROMdepartmentsWHERE location_id IN (1400, 1700)) ;#返回其他工种中比job_id为IT_PROG部门任意工资低的员工#工号,姓名,job_id以及salarySELECTemployee_id,last_name,job_id,salaryFROMemployeesWHERE salary <(SELECTMAX(salary)FROMemployeesWHERE job_id = 'IT_PROG')AND job_id !='IT_PROG';#返回其他工种中比job_id为IT_PROG部门所有工资低的员工#工号,姓名,job_id以及salarySELECTemployee_id,last_name,job_id,salaryFROMemployeesWHERE salary <(SELECTMIN(salary)FROMemployeesWHERE job_id = 'IT_PROG')AND job_id !='IT_PROG';*********************************3.行子查询#查询员工编号最小并且工资最高的员工信息SELECT*FROMemployeesWHERE employee_id =(SELECTMIN(employee_id)FROMemployees)AND salary =(SELECTMAX(salary)FROMemployees)
2)SELECT 后面
#查询每个部门的员工个数SELECTd.*,(SELECTCOUNT(*)FROMemployees eWHERE e.department_id = d.department_id)FROMdepartments d ;#查询员工号等于102的部门名SELECTdepartment_nameFROMdepartmentsWHERE department_id =(SELECTdepartment_idFROMemployeesWHERE employee_id = 102) ;
3)FROM 后面
#查询每个部门平均工资的工资等级SELECTgrade_level ,aa.department_idFROM(SELECTAVG(salary) ag,department_idFROMemployeesGROUP BY department_id) aaINNER JOIN job_grades jON aa.ag BETWEEN lowest_salAND highest_sal ;
4)exists后面(相关子查询)
#查询有员工的部门名SELECT department_name FROM departments dWHERE EXISTS(SELECT * FROM employees e WHERE d.department_id=e.department_id);#查询没有女朋友的男生信息SELECT bo.* FROM boys bo WHEREbo.`id` NOT IN(SELECT boyfriend_id FROM beauty);
5)子查询经典案例祥讲
1.查询工资最低的员工信息:last_name,salarySELECT last_name,salary FROM employeesWHERE salary=(SELECT MIN(salary) FROM employees);2.查询平均工资最低的部门信息SELECT * FROM departments WHERE department_id=(SELECT department_id FROM employees GROUP BY department_id ORDER BY AVG(salary)LIMIT 1)3.查询平均工资最低的部门信息和该部门的平均工资SELECT d.*,a1.ag FROM departments d JOIN(SELECT AVG(salary) ag,department_id FROM employees GROUP BY department_id ORDER BY AVG(salary)LIMIT 1) a1ON d.department_id=a1.department_id4.查询平均工资最高的job信息SELECT j.* FROM jobs j WHERE j.job_id=(SELECT job_id FROM employeesGROUP BY job_id ORDER BY AVG(salary) DESC LIMIT 1)5.查询平均工资高于公司平均工资的部门有哪些SELECT department_id FROM(SELECT department_id ,AVG(salary) AS avg1 FROM employees GROUP BY department_id) e1WHERE e1.avg1>(SELECT AVG(salary) AS avg2 FROM employees)6.查询出公司中所有manager的详细信息SELECT * FROM employeesWHERE employee_id IN(SELECT DISTINCT manager_id FROM employees);7.各个部门中,最高工资中最低的那个部门的最低工资是多少SELECT MIN(salary) FROM employees GROUP BY department_idHAVING department_id=(SELECT department_id FROM employees GROUP BY department_id ORDER BY MAX(salary)LIMIT 1)8.查询平均工资最高的部门的manager的详细信息:last_name,department_id,email,salarySELECT last_name,department_id,email,salary FROM employees WHERE employee_id=(SELECT manager_id FROM departments WHERE department_id=(SELECT department_id FROM employees GROUP BY department_id ORDER BY AVG(salary)DESC LIMIT 1))
8.分页查询
**语法:limit(currentPage-1)size,size
#查询前五条员工信息SELECT * FROM employees LIMIT 0,5;#查询第11-25条员工信息SELECT * FROM employees LIMIT 10,15;#查询有奖金的员工,并且工资最高的前十名显示出来SELECT * FROM employeesWHERE commission_pct IS NOT NULLORDER BY salary DESCLIMIT 0 ,10;
9.联合查询
要查询的结果来自于多个表,且多个表没有直接的连接关系,单查询的信息一致时
特点:
1.要求多条查询语句的查询列数是一致的
2.要求多条查询语句的查询的每一列的类型和顺序最好一致
3.union关键字默认去重,如果使用union all 可以不去除重复项
案例:查询员工部门编号大于90或邮箱包含a的员工信息SELECT * FROM employees WHERE department_id>90UNIONSELECT * FROM employees WHERE email LIKE '%a%';
三,DML数据操作语言
插入insert
一:插入语句#插入beauty一行数据INSERT INTO beauty(NAME,sex,borndate,phone,photo,boyfriend_id)VALUES('波多野吉依','女','1998-11-11','13342969497',NULL,10)#可以为null的列如何不插入值直接写null,或列名少写一列INSERT INTO beauty(NAME,sex,borndate,phone,photo,boyfriend_id)VALUES('小泽玛利亚','女','1999-11-11','13342456497',NULL,11)INSERT INTO beauty VALUES(15,'马蓉','女','1989-11-11','13342456123',NULL,12);INSERT INTO beauty SET id=16,NAME='刘亦菲', sex='女',borndate='1989-10-01',phone='15945231056',boyfriend_id=16;#insert 嵌套子查询,将一个表的数据插入另一张表INSERT INTO beauty (NAME,sex,borndate,phone,boyfriend_id)SELECT '妲己','女','1111-11-11','13146587954',0;
修改update
二,修改UPDATE beauty SET phone='110' WHERE id=16;多表修改:sql99UPDATE 表1 别名INNER|LEFT|RIGHT JOIN 表2 别名ON 连接条件SET 列=值WHERE 筛选条件#修改张无忌的女朋友手机号为114UPDATE beauty gINNER JOIN boys bON g.boyfriend_id=b.idSET g.phone='114'WHERE b.boyName='张无忌';#修改没有男朋友的女生的男朋友编号都为4号UPDATE beauty gLEFT JOIN boys bON g.`boyfriend_id`=b.idSET g.`boyfriend_id`=4WHERE b.id=NULL;
删除delete
三,删除DELETE 和 TRUNCATE 的区别:1.delete可以加where条件,truncate不行2.truncate删除效率高3.加入要删除的表中有自增列,用delete删除整个表后在插入数据,从断点处开始插入用truncate删除后在插入数据,从1开始。4.truncate删除没有返回值,delete有返回值5.truncate删除不能回滚,delete删除可以回滚DELETE FROM beauty WHERE id=17;语法:truncate TABLE 表名;#删除张无忌的女朋友的信息DELETE g FROM beauty gINNER JOIN boys bON g.boyfriend_id=b.idWHERE b.id=1;#删除黄晓明以及他女朋友的信息DELETE b,g FROM beauty gINNER JOIN boys bON b.`id`=g.`boyfriend_id`WHERE b.`boyName`='黄晓明';多表删除 :TRUNCATETRUNCATE TABLE boys
四,DDL数据定义语言
1.库和表的管理
一,库的管理创建 CREATECREATE DATABASE IF NOT EXISTS mydb1 ;修改 ALTER1.更改字符集ALTER DATABASE mydb1 CHARACTER SET utf8;删除 DROPDROP DATABASE IF EXISTS school;二,表的管理创建 CREATECREATE TABLE book(id INT PRIMARY KEY,b_name VARCHAR(30),price DOUBLE,author_id INT ,publishDate DATE);DESC book ;CREATE TABLE author(id INT PRIMARY KEY ,au_name VARCHAR(20),nation VARCHAR(10));DESC author;修改 ALTER1.修改列名ALTER TABLE book CHANGE COLUMN publishDate pub_date DATETIME;2.修改列的类型或约束ALTER TABLE book MODIFY COLUMN pub_date DATE;3.添加新列ALTER TABLE author ADD COLUMN annual DOUBLE;4.删除新列ALTER TABLE author DROP COLUMN annual;5.修改表名ALTER TABLE author RENAME TO book_author;删除 DROPDROP TABLE IF EXISTS my_employee;SHOW TABLES;复制1.仅仅复制表的结构CREATE TABLE copy LIKE book_author;2.复制表的结构加数据CREATE TABLE copy2SELECT * FROM book_author;3.复制部分结构CREATE TABLE copy3SELECT id,au_nameFROM book_authorWHERE id=0;
2.数据类型
数值型
1.整型
| TINYINT | SMALLINT | MEDIUMINT | INT/INTEGER | BIGINT |
|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 8 |
如何设置无符号和有符号(默认有符号)DROP TABLE tab_int;CREATE TABLE tab_int(t1 INT,t2 INT UNSIGNED);INSERT INTO tab_int(t1,t2) VALUES(-1,1);DESC tab_int;
1)如果插入的数值超出了整形的范围,会报out of range异常,并且插入
临界值。
2)如果不设置长度,会有默认的长度。
长度代表了显示的最大宽度,如果不够会用0在左边填充,但必须搭配
zerofill使用。
2.小数
①定点数
dec(M,D)
②浮点数
float(4) ,double(8)
M,D的意思:M指定一共多少位,D指定小数几位,超出会四舍五入。
MD都可以省略,
如果是dec,则M默认为10,D默认为0
如果是浮点数,则会根据插入数值的精度改变精度
定点型精度相对较高。
3.字符型
①较短的文本
CHAR(M)默认为1,VARCHAR(M)
M:字符数
char:固定长度字符,比较耗费空间,但是效率高。
varchar:可变长度字符
ENUM 枚举类CREATE TABLE tab_char(t1 ENUM('a','c','b'));SET 集合CREATE TABLE tab_set(s1 SET('a','b','c','d'));INSERT INTO tab_set(s1) VALUES('a,b');
BINARY:保存较短的二进制。
②较长的文本
text(文本),BLOB(较大的二进制)
4.日期型
DATE:日期
DATETIME:日期加时间,8字节
timestamp:跟时区有关系,建议使用,4字节
time:时间
year:年
CREATE TABLE tab_date(t1 DATETIME,t2 TIMESTAMP);INSERT INTO tab_date(t1,t2)VALUES(NOW(),NOW());SELECT * FROM tab_date;SET time_zone='+9:00';#设置时区为东9区
3.常见约束
含义:一种限制,用于限制表中的数据,保证数据的一致性。
- NOT NULL
- DEFAULT
- PRIMARY KEY 唯一,且不为空
- UNIQUE 唯一,可以为空
- CHECK Mysql不支持
- FOREIGN KEY 外键约束,用于限制两个表的关系,
用于保证该字段的值必须来自于主表的关联列的值。
约束的分类:
列级约束:除外键约束
表级约束:除了非空,默认。
CREATE TABLE 表名(
字段1 字段类型 列级约束,
字段2 字段类型 列级约束,
表级约束
);
#创建表时添加列级约束DROP TABLE tab_test;CREATE TABLE tab_test(id INT PRIMARY KEY,stu_name VARCHAR(20) NOT NULL,gender CHAR DEFAULT '男',seat_id INT UNIQUE,major_id INT REFERENCES tab_major(id));CREATE TABLE tab_major(id INT PRIMARY KEY ,major_name VARCHAR(20) NOT NULL);DESC tab_test;SHOW INDEX FROM tab_test;#查看索引信息#添加表级约束CREATE TABLE tab_test(id INT PRIMARY KEY AUTO_INCREMENT,stu_name VARCHAR(20) NOT NULL,gender CHAR DEFAULT '男',seat_id INT UNIQUE,major_id INT ,CONSTRAINT m_id FOREIGN KEY(major_id) REFERENCES tab_major(id));CONSTRAINT m_id 可以省略
面试题:主键约束和唯一约束的区别:
都可以保证唯一性,
主键不能为空 ,unique 能为空,但是只能有一个null。
主键只能有1个,unique可以有多个。
都允许两个列组合成一个约束。
面试题:外键:
要求在从表设置外键关系
从表的外键列类型和主表的关联列类型一致,名称无要求
要求主表的关联列必须是主键或者唯一键
插入数据应该先插入主表再插入从表
删除数据应该先删除从表,在删除主表
二,修改表时添加约束
CREATE TABLE tab_test2(id INT ,stu_name VARCHAR(20) ,gender CHAR ,seat_id INT ,major_id INT);ALTER TABLE tab_test2 MODIFY COLUMN stu_name VARCHAR(20) NOT NULL ;ALTER TABLE tab_test2 MODIFY COLUMN id INT PRIMARY KEY AUTO_INCREMENT;#添加外键ALTER TABLE tab_test2 ADD FOREIGN KEY(major_id) REFERENCES tab_major(id);
4.标识列
自增长列 AUTO_INCREMENT
特点:
1.表示必须和一个key搭配
2.一个表最多一个标识列
3.标识列类型只能是数值型
4.标识列可以通过set auto_increment_increment=3;设置步长
CREATE tab_auto(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(20) NOT NULL);
五,TCL语言:事务控制语言
事务:一个或一组sql语句组成的执行单元,
要么全部执行,要么都不执行。
存储引擎:在MySQL中的数据用各种不同的技术存储在文件中。
通过show ENGINES;来查看mysql支持的存储引擎。
innodb引擎支持事务。
事务的ACID属性:
1.原子性:事务是一个不可分割的工作单位,要么都发生,要么都不发生。
2.一致性:事务必须使数据库从一个一致性状态变为另一个一致性状态。
3.隔离性:一个事务的执行不能被另一个事务干扰。
4.持久性:事务一旦被提交,对数据库事务的改变就是永久性的。
DELETE 和 TRUNCATE 在事务中的区别:
演示deleteSET autocommit=0;START TRANSACTION;DELETE FROM tab_teacher;ROLLBACK;演示 TRUNCATESET autocommit=0;START TRANSACTION;TRUNCATE TABLE tab_teacher;ROLLBACK;DELETE 是直接删除表中数据,truncate是江表删除,创建一张与原来一样的空表。
六,视图
含义:虚拟表,和普通表格一样使用
通过表动态生成的数据
1.创建视图
语法:
CREATE VIEW 视图名
AS
查询语句 ;
# 案例:查询姓名中包含a字符的员工名,部门名和工种信息create view view1 asselect e.last_name,d.department_name ,j.job_title from employees einner join departments d on e.department_id = d.department_idinner join jobs j on e.job_id = j.job_idwhere e.last_name like '%a%';select * from view1;# 案例:查询各个部门的平均工资级别create view view2 asselect j.grade_level ,aa.department_idfrom job_grades jinner join (select avg(salary) avg_s,department_id from employees group by department_id) aaon aa.avg_s between j.lowest_sal and j.highest_sal;select * from view2;# 案例:查询平均工资最低的部门信息create view view3 asselect avg(salary) avg_s ,department_idfrom employeesgroup by department_idorder by avg_s asclimit 1;select * from view3;
2.视图修改
①create OR REPLACE VIEW 视图名 AS 查询语句;
②alter VIEW 视图名 AS 查询语句;
3.删除视图
DROP VIEW v1,v2;
4.查看视图
DESC v1;
#创建视图emp_v1,要求查询电话号码以011开头的员工姓名和工资,邮箱CREATE VIEW emp_v1 ASSELECT last_name ,salary,email FROM employees WHEREphone_number LIKE '%011';#创建视图emp_v2,要求查询部门的最高工资高于12000的部门信息CREATE VIEW v4 ASSELECT department_id FROM employees GROUP BY department_idHAVING MAX(salary)> 12000;CREATE VIEW emp_v2 ASSELECT * FROM departments WHERE department_id IN(SELECT * FROM v4);
5.视图的更新
视图的可更新性和视图中查询的定义有关,以下类型的视图是不能更新的。
1.包含以下关键字的sql语句:分组函数,distinct,group by,having,union
2.常量视图
3.select中包含子查询的
4.join
5.from 一个不能更新的视图
6.where子句的子查询引用了from子句的表
6.视图和表的对比:
| 创建语法的关键字 | 是否实际占用物理空间 | 使用 | |
|---|---|---|---|
| 视图 | CREATE VIEW | 只是保存了sql逻辑 | 增删改查,一般不能增删改 |
| 表 | CREATE TABLE | 占用 | 增删改查 |
七,变量
系统变量 :变量由系统提供,不是用户自定义,属于服务器层面。
查看系统所有变量:show GLOBAL VARIABLES;
查看满足条件的部分系统变量: SHOW GLOBAL VARIABLES LIKE ‘%char%’;
查看指定的某个系统变量的值: SELECT @@global.autocommit;
为某个系统变量赋值:set @@global.系统变量名=值;
全局变量:GLOBAL
作用域:服务器每次启动将为所有的全局变量赋初始值,针对于所有的会话有效,但不能
跨重启。
会话变量:SESSION
作用域:针对当前的会话有效。
用户自定义变量
用户变量
声明: SET/SELECT @用户变量名 :=值;
赋值:通过 SELECT 字段 INTO 变量名;或 SET/SELECT @用户变量名 :=值;
使用:select @用户变量名;
应用在任何地方。
作用域:针对当前会话和连接有效。
局部变量
作用域:作用在定义它的begin END 块中。
声明: DECLARE 变量名 类型 (default 值);
赋值:通过 SELECT 字段 INTO 变量名;或 SET/SELECT @变量名 :=值;
使用:select @变量名;
只能放在begin END 中的第一句话
八,存储过程和函数
存储过程:
一组预先定义好的sql语句集合,理解成批处理语句。
1.提高代码的重用性
2.简化操作
3.减少了编译次数并且减少了和数据库服务器的连接次数,提高了效率。
1.创建语法:
CREATE PROCEDURE 存储过程名(参数列表)
BEGIN
一组合法的sql语句;
END
参数列表:参数模式 参数名 参数类型
参数模式:
in:该参数可以作为输入,也就是该参数需要调用方传入值
OUT :该参数可以作为输出,也就是该参数可以作为返回值
inout:该参数既可以作为输入又可以作为输出
如果存储过程只有一句话,begin END 可以省略
存储过程体中的每条sql语句的结尾需要必须加分号,
存储过程的结尾可以使用 DELIMITER 重新设置。
2.调用
CALL 存储过程名(实参列表);
3.案例
#插入到admin表中五条记录DELIMITER $CREATE PROCEDURE my_a()BEGININSERT INTO admin(username,PASSWORD) VALUES('yin','666');INSERT INTO admin(username,PASSWORD) VALUES('aa','123');INSERT INTO admin(username,PASSWORD) VALUES('bb','666');INSERT INTO admin(username,PASSWORD) VALUES('cc','123');INSERT INTO admin(username,PASSWORD) VALUES('dd','666');END $#创建存储过程实现 根据女生名查询对应的男生信息DELIMITER $CREATE PROCEDURE my_b(IN beauty_name VARCHAR(20))BEGINSELECT bo.*FROM boys boRIGHT JOIN beauty b ON bo.id=b.boyfriend_idWHERE b.name=beauty_name;END $CALL my_b('热巴');#根据女生名返回他的男朋友名DELIMITER $CREATE PROCEDURE my_d(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20))BEGINSELECT bo.boyName INTO boyNameFROM boys boINNER JOIN beauty b ON bo.id=b.boyfriend_idWHERE b.name=beautyName;END $CALL my_d('小昭',@b_name);SELECT @b_name;#传入两个值a,b,最终翻倍返回a和bDELIMITER $CREATE PROCEDURE my_e(INOUT a INT ,INOUT b INT )BEGINSET a=a*2;SET b=b*2;END $SET @m=10;SET @n=20;CALL my_e(@m,@n);SELECT @m,@n;
4.删除存储过程
DROP PROCEDURE 存储过程名DROP PROCEDURE my_a;
5.查看存储过程的信息
SHOW CREATE PROCEDURE my_b;
函数
存储过程可以有0/n个返回值:适合批量增删改
函数有且仅有一个返回值:适合查询
1.创建
DELIMITER $CREATE FUNCTION 函数名(参数列表) RETURNS 返回类型BEGINEND
注意:
参数列表:参数名,参数类型
一定会有return语句
2.使用
SELECT 函数名(参数列表)
#返回公司员工个数DELIMITER $CREATE FUNCTION my_f1() RETURNS INTBEGINDECLARE c INT DEFAULT 0 ;SELECT COUNT(*) INTO c FROM employees;RETURN c;END $SELECT my_f1();#根据员工名返回他的工资DELIMITER $CREATE FUNCTION my_f2(NAME VARCHAR(20)) RETURNS DOUBLEBEGINDECLARE c DOUBLE;SELECT salary INTO c FROM employees WHERE last_name=NAME;RETURN c;END $SET @a='Hunold';SELECT my_f2(@a);
3.查看
SHOW CREATE FUNCTION my_f2;
4.删除
DROP FUNCTION my_f2;
九,流程控制
分支结构
1.if (表达式1,表达式2,表达式3)
如果表达式1成立,就返回表达式2的值,否则返回表达式3的值。
应用在任何地方
2.case
1)switch-CASE
语法:
CASE 要判断的字段或者表达式
WHEN 常量1 THEN 要显示的值1或者语句1
WHEN 常量2 THEN 要显示的值2或者语句2
…
ELSE 要显示的值n或者语句n;
案例:查询员工的工资,要求部门号==30,显示的工资为1.1倍,部门号==40,显示的工资为1.2倍,部门号==50,显示的工资为1.3倍,其他部门,显示原有工资。SELECTsalary AS 原始工资,department_id ,CASEdepartment_idWHEN 30THEN salary * 1.1WHEN 40THEN salary * 1.2WHEN 50THEN salary * 1.3ELSE salaryEND AS 新工资FROMemployees ;
2)CASE 使用2:
语法:
CASE
WHEN 条件1 THEN 要显示的值1或语句1
WHEN 条件2 THEN 要显示的值2或语句2
…
ELSE 要显示的值n或语句n
END
案例:查询员工的工资情况如果>2w,显示A如果>1.5w,显示B如果>1w,显示C否则,显示DSELECTsalary,CASEWHEN salary > 20000THEN 'A'WHEN salary > 15000THEN 'B'WHEN salary > 10000THEN 'C'ELSE 'D'END AS 工资等级 FROM employees可以放在任何地方#创建存储过程,根据传入的成绩,显示等级,90A,80B,70C,60D ,FDELIMITER $CREATE PROCEDURE my_1(IN score INT)BEGINCASEWHEN score BETWEEN 90 AND 100THEN SELECT 'A';WHEN score BETWEEN 80 AND 90THEN SELECT 'B';WHEN score BETWEEN 70 AND 80THEN SELECT 'C';WHEN score BETWEEN 70 AND 60THEN SELECT 'D';ELSE SELECT 'E';END CASE;END $CALL my_1(95);
3.if
语法:
IF 条件1 THEN 语句1;
ELSEIF 条件2 THEN 语句2;
…
ELSE 语句n;
END IF;
只能用在begin end中
#创建存储过程,根据传入的成绩,返回等级,90A,80B,70C,60D ,FDELIMITER $CREATE FUNCTION my_2( score INT) RETURNS CHARBEGINIF score >=90 THEN RETURN'A';ELSEIF score >=80 THEN RETURN'B';ELSEIF score >=70 THEN RETURN'C';ELSEIF score >=60 THEN RETURN'D';ELSE RETURN'E';END IF;END $SELECT my_2(85);
循环结构
在存储过程或函数里面使用
1.while
语法:
标签:WHILE 循环条件 DO
循环体;
END WHILE 标签;
循环控制和标签搭配使用
2.loop
语法:
标签: LOOP
循环体;
END LOOP 标签;
3.repeat
语法:
标签: REPEAT
循环体;
UNTIL 结束循环的条件
END REPEAT 标签;
循环控制
ITERATE 类似continue
LEAVE 类似break
left join==left outer join
a left join b 就是取a和b的交集加a剩下的部分
inner join
a inner join b就是取交集

