MySQL8
2022-12-12 11:05:49 29 举报
AI智能生成
MySQL是一个开源的关系型数据库管理系统,由瑞典公司MySQL AB开发,现在属于甲骨文公司。它使用结构化查询语言(SQL)作为访问和管理数据的主要方式。MySQL被广泛应用于各种类型的应用中,包括网站、网络应用、嵌入式设备等。 MySQL具有高性能、稳定性强、易于使用和扩展等优点。它支持多种操作系统,如Windows、Linux、MacOS等,并且提供了丰富的客户端工具和API,方便开发者进行数据库操作和管理。此外,MySQL还支持多种存储引擎,如InnoDB、MyISAM等,可以根据不同的应用场景选择合适的存储引擎。
作者其他创作
大纲/内容
认识MySQL
数据库的好处
数组、集合等存储在内存:断电即丢;
文件:不方便查询
文件:不方便查询
数据库:
1、持久化数据到本地
2、可以实现结构化查询,方便管理
1、持久化数据到本地
2、可以实现结构化查询,方便管理
DB、DBMS、SQL的区别
程序员使用数据库管理系统通过结构化查询语言操作数据库
MySQL的卸载和安装
Mysql的配置文件(注:配置修改后需要重启服务)
找到mysql安装路径下的my.ini配置文件,可以修改port(端口)、basedir(安装目录)、datadir(建库目录)、character-set-server(字符集)、default-storage-engine=INNODB(数据库引擎)
Mysql卸载
删除软件
删除Program Files(x86)下的mysql文件夹
删除ProgramData下的文件夹
清理注册表:
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Eventlog\Application\MySQL 目录
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Services\Eventlog\Application\MySQL 目录
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\MySQL 目录
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControl001\Services\MySQL 目录
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControl002\Services\MySQL 目录
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MySQL 目录
删除Program Files(x86)下的mysql文件夹
删除ProgramData下的文件夹
清理注册表:
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Eventlog\Application\MySQL 目录
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Services\Eventlog\Application\MySQL 目录
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\MySQL 目录
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControl001\Services\MySQL 目录
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControl002\Services\MySQL 目录
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MySQL 目录
Mysql服务的启动和停止
net start|stop MySQL80(这里是数据库服务名称)
数据库的登录和退出
mysql 【-h localhost -P 3306】 -u root -p
MySQL常见命令
information_schema——元数据信息
mysql
performance_schema——收集性能信息、参数
test——测试数据库
show tables from mysql;——查询mysql数据库中有哪些表
show database;——查询所在库
show variables like '%char%'——查询变量
create table stuinfo(id int,name varchar(20));——建表
desc stuinfo;——查看表结构
insert into stuinfo(id,name) values(1,'Mary');
select version();——查看mysql版本
mysql --version|-V(注:dos命令)
mysql
performance_schema——收集性能信息、参数
test——测试数据库
show tables from mysql;——查询mysql数据库中有哪些表
show database;——查询所在库
show variables like '%char%'——查询变量
create table stuinfo(id int,name varchar(20));——建表
desc stuinfo;——查看表结构
insert into stuinfo(id,name) values(1,'Mary');
select version();——查看mysql版本
mysql --version|-V(注:dos命令)
DQL
排序查询
MySQL的执行顺序
select 查询列表《3》
from 表《1》
【where 筛选条件】《2》
order by 排序列表【asc|desc】《4》(注:排序列表支持单个字段、多个字段、函数、表达式、别名)
【limit】
from 表《1》
【where 筛选条件】《2》
order by 排序列表【asc|desc】《4》(注:排序列表支持单个字段、多个字段、函数、表达式、别名)
【limit】
按表达式排序
select * from table 【where】order by 排序列表【asc/desc】
select *,salary*12*(1+IFNULL(commission_pct,0)) 年薪 from employees order by salary*12*(1+IFNULL(commission_pct,0)) desc;
select *,salary*12*(1+IFNULL(commission_pct,0)) 年薪 from employees order by salary*12*(1+IFNULL(commission_pct,0)) desc;
按别名排序
select *,salary*12*(1+IFNULL(commission_pct,0)) 年薪 from employee order by 年薪 desc;
按函数排序
SELECT LENGHT(last_name) 字节长度,last_name,salary FROM employees ORDER BY LENGTH(last_name) DESC;
常见函数
概念
类似于java的方法,将一组逻辑语句封装在方法体中,对外暴露方法名
好处
1、隐藏了实现细节 2、提高代码的重用性
调用
select 函数名(实参列表) 【from 表】;
分类
单行函数:concat、length、ifnull等
字符函数
length 获取参数值的字节个数
SELECT LENGTH('john')
concat 拼接字符串
SELECT CONCAT(last_name,'_',first_name) FROM employees
upper/lower
SELECT UPPER('myName');
SELECT LOWER('myName');
SELECT CONCAT(UPPER(last_name),LOWER(first_name)) 姓名 FROM employees;
SELECT LOWER('myName');
SELECT CONCAT(UPPER(last_name),LOWER(first_name)) 姓名 FROM employees;
substr/substring 截取从指定索引处开始的字符(注:MySQL数据库索引从1开始)
SELECT SUBSTR('abcd',2);
SELECT SUBSTR('abcd',2,1);
SELECT CONCAT(UPPER(substr(last_name,1,1)),'_',LOWER(SUBSTR(first_name,2))) 姓名 FROM employees;
select substr(email,1,instr(email,'@')-1) 用户名 from stu;(查询所有学生邮箱的用户名)
SELECT SUBSTR('abcd',2,1);
SELECT CONCAT(UPPER(substr(last_name,1,1)),'_',LOWER(SUBSTR(first_name,2))) 姓名 FROM employees;
select substr(email,1,instr(email,'@')-1) 用户名 from stu;(查询所有学生邮箱的用户名)
instr 返回字符串第一次出现的索引,如果找不到返回0
SELECT INSTR('abcd','d');
trim 截取去除两边的空格或指定的字符后的字符串
SELECT TRIM(' a b c ');
SELECT TRIM('a' FROM 'aaaaaaaaaa雪aaaaa丽aaaaaaaaa');
SELECT TRIM('aa' FROM 'aaaaaaaaaa雪aaaaa丽aaaaaaaaa');
SELECT TRIM('a' FROM 'aaaaaaaaaa雪aaaaa丽aaaaaaaaa');
SELECT TRIM('aa' FROM 'aaaaaaaaaa雪aaaaa丽aaaaaaaaa');
lpad/rpad 指定的字符实现左/右填充指定长度
SELECT LPAD('kx',6,'*');
SELECT RPAD('kx',10,'ab');
SELECT RPAD('kx',10,'ab');
replace 替换所有
SELECT REPLACE('周芷若张无忌爱上周芷若','周芷若','赵敏')
数学函数
round 四舍五入(可以先求绝对值再标正负)
SELECT ROUND(-1.55);
SELECT ROUND(1.567,2);
SELECT ROUND(1.567,2);
ceil/floor 向上/下取整
SELECT CEIL(-1.02);
SELECT FLOOR(-9.12);
SELECT FLOOR(-9.12);
truncate 截断
SELECT TRUNCATE(1.69999,2);
mod 取余
mod(a,b)《==》a-a/b*b
SELECT MOD(10,3);
SELECT 10%3;)
SELECT MOD(10,3);
SELECT 10%3;)
rand 获取随机数,返回0——1之间的小数
日期函数
now 返回当前系统日期+时间
SELECT NOW();
curdate 返回当前系统日期
SELECT CURDATE();
curtime 返回当前系统时间
SELECT CURTIME();
可以获取指定的部分,年、月、日、时、分、秒
SELECT YEAR(NOW()) 年;
SELECT YEAR(hiredate) 年 FROM employees;
SELECT MONTHNAME(hiredate) 月 FROM employees;
SELECT YEAR(hiredate) 年 FROM employees;
SELECT MONTHNAME(hiredate) 月 FROM employees;
str_to_date 将日期格式的字符串转换成指定格式的日期
SELECT STR_TO_DATE('1998-3-2','%Y-%c-%d');
SELECT * FROM employees WHERE hiredate = STR_TO_DATE('4-3 1992','%m-%d %Y');
SELECT * FROM employees WHERE hiredate = STR_TO_DATE('4-3 1992','%m-%d %Y');
date_format 将日期转换成字符
datediff 返回两个日期相差的天数
monthname 以英文形式返回月
SELECT MONTHNAME('2022-11-1');
举例
#查询有奖金的员工名和入职日期(xx月/xx日 xx年)
SELECT last_name,DATE_FORMAT(hiredate,'%m月/%d日 %y年') FROM employees WHERE commission_pct IS NOT NULL;
SELECT last_name,DATE_FORMAT(hiredate,'%m月/%d日 %y年') FROM employees WHERE commission_pct IS NOT NULL;
其他函数
SELECT VERSION();————数据库版本
SELECT DATABASE();————查看当前数据库
SELECT USER();————查看当前登录用户
结果:root@localhost
SELECT MD5('贵雪丽');————MySQL8 MD5加密,MySQL5 使用PASSWORD()函数加密
结果:1b1e9c25a408bcea606a3513da3b7807
流程控制函数
if函数 (if else的效果)
SELECT IF(10<5,'大','小');
SELECT last_name,commission_pct,IF(commission_pct IS NULL,'没奖金,呵呵','有奖金,哈哈') FROM employees;
SELECT last_name,commission_pct,IF(commission_pct IS NULL,'没奖金,呵呵','有奖金,哈哈') FROM employees;
case函数的使用一:switch case的效果
JAVA中
switch(变量或表达式){
case 常量1:语句1;break;
...
default:语句n;break;
}
switch(变量或表达式){
case 常量1:语句1;break;
...
default:语句n;break;
}
MySQL中
case 要判断的字段或表达式
when 常量1 then 要显示的值1或语句1;
when 常量2 then 要显示的值2或语句2;
...
else 要显示的值n或语句n;
end
case 要判断的字段或表达式
when 常量1 then 要显示的值1或语句1;
when 常量2 then 要显示的值2或语句2;
...
else 要显示的值n或语句n;
end
案例:查询员工的工资,要求
部门号=30,显示的工资为1.1倍
部门号=40,显示的工资为1.2倍
部门号=50,显示的工资为1.3倍
部门号=30,显示的工资为1.1倍
部门号=40,显示的工资为1.2倍
部门号=50,显示的工资为1.3倍
SELECT salary 原始工资,department_id,
case department_id
when 30 then salary*1.1
when 40 then salary*1.2
when 50 then salary*1.3
ELSE salary
END 现在工资
FROM employees;
case department_id
when 30 then salary*1.1
when 40 then salary*1.2
when 50 then salary*1.3
ELSE salary
END 现在工资
FROM employees;
case函数的使用二:类似于 多重if
JAVA中
if(条件1){
语句1;
}else if(条件2){
语句2;
}...
else{
语句n;
}
if(条件1){
语句1;
}else if(条件2){
语句2;
}...
else{
语句n;
}
MySQL中
case
when 条件1 then 要显示的值1或语句1
when 条件2 then 要显示的值2或语句2
...
else 要显示的值n或语句n;
end
case
when 条件1 then 要显示的值1或语句1
when 条件2 then 要显示的值2或语句2
...
else 要显示的值n或语句n;
end
案例:查询员工工资的情况
工资大于20000,A级别
工资大于15000,B级别
工资大于10000,C级别
否则,D级别
工资大于20000,A级别
工资大于15000,B级别
工资大于10000,C级别
否则,D级别
SELECT salary 原始工资,
case
when salary>20000 then 'A'
when salary>15000 then 'B'
when salary>10000 then 'C'
ELSE 'D'
END 工资级别
FROM employees;
case
when salary>20000 then 'A'
when salary>15000 then 'B'
when salary>10000 then 'C'
ELSE 'D'
END 工资级别
FROM employees;
分组函数
功能
做统计使用,又称为统计函数、聚合函数、组函数。
分类
sum求和、avg平均值、max最大值、min最小值、count计算非空个数
特点
sum/avg处理数值型,max/min/count处理任何类型
简单使用
SELECT SUM(salary) FROM employees;
参数支持哪些类型
SELECT MAX(last_name),MIN(last_name),COUNT(last_name) FROM employees;
以上分组函数都忽略null值
SELECT SUM(commission_pct),AVG(commission_pct),SUM(commission_pct)/35,SUM(commission_pct)/107 FROM employees;
SELECT MAX(commission_pct),MIN(commission_pct) FROM employees;
SELECT MAX(commission_pct),MIN(commission_pct) FROM employees;
和distinct搭配
SELECT SUM(DISTINCT salary),SUM(salary) FROM employees;
SELECT COUNT(DISTINCT salary),COUNT(salary) FROM employees;
SELECT COUNT(DISTINCT salary),COUNT(salary) FROM employees;
count函数的详细介绍
SELECT COUNT(salary) FROM employees;
SELECT COUNT(*) FROM employees;————效率高
SELECT COUNT(1) FROM employees;
SELECT COUNT(*) FROM employees;————效率高
SELECT COUNT(1) FROM employees;
和分组函数一同查询的字段要求是group by后的字段
SELECT datediff('1998-10-25','1999-04-08');————datediff表示两个时间相差的天数
SELECT MAX(hiredate),MIN(hiredate),datediff(MAX(hiredate),MIN(hiredate)) FROM employees;
SELECT MAX(hiredate),MIN(hiredate),datediff(MAX(hiredate),MIN(hiredate)) FROM employees;
分组查询
语法
SELECT column,group_function(column)
FROM table
【WHERE condition】
【GROUP BY group_by_expression】
【ORDER BY column】
FROM table
【WHERE condition】
【GROUP BY group_by_expression】
【ORDER BY column】
特点
分组查询中的筛选条件分为两类
分组函数做条件肯定放在having子句中
考虑性能,能用分组前筛选的,就优先使用分组前筛选
group by子句支持单个字段分组,多个字段分组(多个字段之间用逗号隔开没有顺序要求),表达式或函数()
也可以添加排序(排序放在整个分组查询的最后)
按单个字段分组
#案例1:查询每个工种的最高工资
SELECT MAX(salary),job_id FROM employees GROUP BY job_id;
SELECT MAX(salary),job_id FROM employees GROUP BY job_id;
#案例2:查询每个位置上的部门个数
SELECT COUNT(*),location_id FROM departments GROUP BY location_id;
SELECT COUNT(*),location_id FROM departments GROUP BY location_id;
#案例3:查询有奖金的每个领导手下员工的最高工资
SELECT MAX(salary),manager_id FROM employees WHERE commission_pct IS NOT null GROUP BY manager_id;
SELECT MAX(salary),manager_id FROM employees WHERE commission_pct IS NOT null GROUP BY manager_id;
#案例4: 查询哪个部门的员工个数>2
SELECT COUNT(*),department_id FROM employees GROUP BY department_id HAVING COUNT(*)>2;
SELECT COUNT(*),department_id FROM employees GROUP BY department_id HAVING COUNT(*)>2;
#案例5:查询每个工种有奖金的员工的最高工资>12000的工种编号和最高工资
#①查询每个工种有奖金的员工的最高工资
SELECT MAX(salary),job_id FROM employees WHERE commission_pct IS NOT null GROUP BY job_id;
#②根据①结果继续筛选,最高工资>12000
SELECT job_id,MAX(salary) FROM employees WHERE commission_pct IS NOT null GROUP BY job_id HAVING MAX(salary)>12000;
#①查询每个工种有奖金的员工的最高工资
SELECT MAX(salary),job_id FROM employees WHERE commission_pct IS NOT null GROUP BY job_id;
#②根据①结果继续筛选,最高工资>12000
SELECT job_id,MAX(salary) FROM employees WHERE commission_pct IS NOT null GROUP BY job_id HAVING MAX(salary)>12000;
#案例6:查询领导编号>102的每个领导手下的最低工资>5000的领导编号是哪个,以及其最低工资
#①查询每个领导手下的员工固定最低工资
SELECT MIN(salary),manager_id FROM employees GROUP BY manager_id;
#②添加筛选条件:领导编号>102
SELECT MIN(salary),manager_id FROM employees WHERE manager_id>102 GROUP BY manager_id;
#③添加筛选条件:最低工资>5000
SELECT MIN(salary),manager_id FROM employees WHERE manager_id>102 GROUP BY manager_id HAVING MIN(salary)>5000;
#①查询每个领导手下的员工固定最低工资
SELECT MIN(salary),manager_id FROM employees GROUP BY manager_id;
#②添加筛选条件:领导编号>102
SELECT MIN(salary),manager_id FROM employees WHERE manager_id>102 GROUP BY manager_id;
#③添加筛选条件:最低工资>5000
SELECT MIN(salary),manager_id FROM employees WHERE manager_id>102 GROUP BY manager_id HAVING MIN(salary)>5000;
#案例7:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数>5的有哪些
SELECT COUNT(*),LENGTH(last_name) FROM employees GROUP BY LENGTH(last_name) HAVING COUNT(*)>5;
SELECT COUNT(*),LENGTH(last_name) FROM employees GROUP BY LENGTH(last_name) HAVING COUNT(*)>5;
按多个字段分组
#案例1:查询每个部门每个工种的员工的平均工资
SELECT AVG(salary),department_id 部门,job_id 工种 FROM employees GROUP BY 部门,工种;
SELECT AVG(salary),department_id 部门,job_id 工种 FROM employees GROUP BY 部门,工种;
#案例2:查询每个部门每个工种的员工的平均工资,并且按平均工资的高低排序
SELECT AVG(salary),department_id 部门,job_id 工种 FROM employees GROUP BY 部门,工种 ORDER BY AVG(salary) desc;
SELECT AVG(salary),department_id 部门,job_id 工种 FROM employees GROUP BY 部门,工种 ORDER BY AVG(salary) desc;
连接查询
含义
又称多表查询,当查询的字段来自于多个表时,就会用到连接查询
笛卡尔乘积现象
表1 有m行,表2有n行,结果=m*n行
分类
按年代分类:
sql92标准:仅支持内连接
sql99【推荐】:支持内连接(等值、非等值、自连接)+外连接(左外、右外)+交叉连接
sql92标准:仅支持内连接
sql99【推荐】:支持内连接(等值、非等值、自连接)+外连接(左外、右外)+交叉连接
按功能分类:
内连接:等值连接、非等值连接、自连接
外连接:左外连接、右外连接、全外连接(mysql不支持)
交叉连接
内连接:等值连接、非等值连接、自连接
外连接:左外连接、右外连接、全外连接(mysql不支持)
交叉连接
sql92标准
语法
select 查询列表
from 表1 别名,表2 别名
where 表1.key=表2.key
【and 筛选条件】
【group by 分组字段】
【having 分组后的筛选】
【order by 排序字段】
from 表1 别名,表2 别名
where 表1.key=表2.key
【and 筛选条件】
【group by 分组字段】
【having 分组后的筛选】
【order by 排序字段】
等值连接
①多表等值连接的结果为多表的交集部分
②n表连接,至少需要n-1个连接条件
③多表的顺序无要求
④一般需要为表起别名
②n表连接,至少需要n-1个连接条件
③多表的顺序无要求
④一般需要为表起别名
#案例1:查询女神名和对应的男神名
SELECT NAME,boyName FROM beauty,boys WHERE boys.id=boyfriend_id;
SELECT NAME,boyName FROM beauty,boys WHERE boys.id=boyfriend_id;
#案例2:查询城市名中第二个字符为o的部门名和城市名
SELECT department_name,city FROM departments d,locations l WHERE d.location_id=l.location_id and SUBSTR(l.city,2,1)='o';
SELECT department_name,city FROM departments d,locations l WHERE d.location_id=l.location_id AND l.city LIKE '_o%';
SELECT department_name,city FROM departments d,locations l WHERE d.location_id=l.location_id and SUBSTR(l.city,2,1)='o';
SELECT department_name,city FROM departments d,locations l WHERE d.location_id=l.location_id AND l.city LIKE '_o%';
非等值连接
#案例1:查询员工的工资和工资级别
SELECT salary,grade_level FROM employees e,job_grades g WHERE salary BETWEEN g.lowest_sal AND g.highest_sal;
SELECT salary,grade_level FROM employees e,job_grades g WHERE salary BETWEEN g.lowest_sal AND g.highest_sal;
自连接
#案例:查询员工名和上级的名称
SELECT e.employee_id,e.last_name,m.employee_id,m.employee_id FROM employees e,employees m WHERE e.manager_id=m.employee_id;
SELECT e.employee_id,e.last_name,m.employee_id,m.employee_id FROM employees e,employees m WHERE e.manager_id=m.employee_id;
注:mysql不支持外连接,oracle、sqlserver支持
sql99标准
select 查询列表
from 表1 别名
join 表2 别名
on 连接条件
【where 筛选条件】
【group by 分组字段】
【having 分组后的筛选条件】
【order by 排序列表】
分类:
内连接:【inner】 join
外连接:
左外:left 【outer】
右外:right 【outer】
全外:full 【outer】
交叉连接:cross
from 表1 别名
join 表2 别名
on 连接条件
【where 筛选条件】
【group by 分组字段】
【having 分组后的筛选条件】
【order by 排序列表】
分类:
内连接:【inner】 join
外连接:
左外:left 【outer】
右外:right 【outer】
全外:full 【outer】
交叉连接:cross
等值连接
on后面放连接条件,where后面放筛选条件,提高分离性,便于阅读
非等值连接
#案例1:查询员工的工资级别
SELECT salary,grade_level FROM job_grades j inner JOIN employees e ON e.salary BETWEEN j.lowest_sal AND j.highest_sal;
SELECT salary,grade_level FROM job_grades j inner JOIN employees e ON e.salary BETWEEN j.lowest_sal AND j.highest_sal;
自连接
#案例1:查询员工的名字、上级的名字
SELECT e.last_name,m.last_name FROM employees e JOIN employees m ON e.manager_id=m.employee_id;
SELECT e.last_name,m.last_name FROM employees e JOIN employees m ON e.manager_id=m.employee_id;
外连接
应用场景
用于查询一个表中有,另一个表没有的记录
特点
外连接的查询结果为主表中的所有记录
如果从表中有和它匹配的,则显示匹配的值
如果从表中没有和它匹配的,则显示null
外连接查询结果=内连接查询结果+主表中有而从表中没有的记录
如果从表中有和它匹配的,则显示匹配的值
如果从表中没有和它匹配的,则显示null
外连接查询结果=内连接查询结果+主表中有而从表中没有的记录
左外连接,left join左边的是主表
右外连接,right join右边的是主表
右外连接,right join右边的是主表
左外和右外交换两个表的顺序,可以实现同样的效果
#引入:查询男朋友 不在男神表的女神名
左外:SELECT b.name,y.* FROM beauty b LEFT OUTER JOIN boys y ON b.boyfriend_id=y.id WHERE y.id IS NULL;
右外:SELECT b.name,y.* FROM boys y RIGHT OUTER JOIN beauty b ON b.boyfriend_id=y.id WHERE y.id IS NULL;
左外:SELECT b.name,y.* FROM beauty b LEFT OUTER JOIN boys y ON b.boyfriend_id=y.id WHERE y.id IS NULL;
右外:SELECT b.name,y.* FROM boys y RIGHT OUTER JOIN beauty b ON b.boyfriend_id=y.id WHERE y.id IS NULL;
#案例1:查询哪个部门没有员工
SELECT e.department_id,d.* FROM departments d LEFT OUTER JOIN employees e ON e.department_id=d.department_id WHERE e.employee_id IS NULL;
SELECT e.department_id,d.* FROM departments d LEFT OUTER JOIN employees e ON e.department_id=d.department_id WHERE e.employee_id IS NULL;
全外连接
select <select_list> FROM A FULL JOIN B ON A.key=B.key;
CROSS JOIN
子查询
含义
出现在其他语句中的select语句,称为子查询或内查询;
外部的其他查询,成为主查询或外查询
外部的其他查询,成为主查询或外查询
分类
按子查询出现的位置:
select后面:
仅仅支持标量子查询
from后面:
支持表子查询
where或having后面(*):
标量子查询(*)、列子查询(*)、行子查询
exists后面(相关子查询):
表子查询
select后面:
仅仅支持标量子查询
from后面:
支持表子查询
where或having后面(*):
标量子查询(*)、列子查询(*)、行子查询
exists后面(相关子查询):
表子查询
按结果集的行列数不同:
标量子查询(结果集只有一行一列)
列子查询(结果集只有一列多行)
行子查询(结果集有一行多列)
表子查询(结果集一般为多行多列)
标量子查询(结果集只有一行一列)
列子查询(结果集只有一列多行)
行子查询(结果集有一行多列)
表子查询(结果集一般为多行多列)
特点
①子查询放在小括号内
②子查询一般放在条件的右侧
③标量子查询,一般搭配着单行操作符使用:> < >= <= = <>
列子查询,一般搭配着多行操作符使用:in any/some/all
②子查询一般放在条件的右侧
③标量子查询,一般搭配着单行操作符使用:> < >= <= = <>
列子查询,一般搭配着多行操作符使用:in any/some/all
where或having后面
标量子查询(单行子查询)
#案例1:谁的工资比Abe1高?
SELECT *
FROM employees
WHERE salary>(SELECT salary FROM employees WHERE last_name='Abel');
SELECT *
FROM employees
WHERE salary>(SELECT salary FROM employees WHERE last_name='Abel');
#案例2:查询工资最少的员工的last_name,job_id和salary
SELECT last_name,job_id,salary FROM employees WHERE salary = (SELECT MIN(salary) FROM employees);
SELECT last_name,job_id,salary FROM employees WHERE salary = (SELECT MIN(salary) FROM employees);
#案例3:查询最低工资大于50号部门最低工资的部门id和其最低工资
SELECT department_id, MIN(salary)
FROM employees GROUP BY department_id HAVING MIN(salary) > (SELECT MIN(salary) FROM employees WHERE department_id=50);
SELECT department_id, MIN(salary)
FROM employees GROUP BY department_id HAVING MIN(salary) > (SELECT MIN(salary) FROM employees WHERE department_id=50);
列子查询(多行子查询)
注:“in”等价于“=ANY”, “not in”等价于“<>ALL”
#案例1:返回location_id是1400或1700的部门中的所有员工姓名
SELECT last_name FROM employees WHERE department_id IN (select department_id from departments where location_id IN (1400,1700));
SELECT last_name FROM employees WHERE department_id IN (select department_id from departments where location_id IN (1400,1700));
#案例2:返回其它工种中比job_id为'IT_PROG'工种任一工资低的员工的员工号、姓名、job_id以及salary
SELECT employee_id,last_name,job_id,salary FROM employees WHERE salary < ANY(SELECT distinct salary FROM employees where job_id='IT_PROG') AND job_id<>'IT_PROG';
或
SELECT employee_id,last_name,job_id,salary FROM employees WHERE salary < (SELECT max(salary) FROM employees where job_id='IT_PROG') AND job_id<>'IT_PROG';
SELECT employee_id,last_name,job_id,salary FROM employees WHERE salary < ANY(SELECT distinct salary FROM employees where job_id='IT_PROG') AND job_id<>'IT_PROG';
或
SELECT employee_id,last_name,job_id,salary FROM employees WHERE salary < (SELECT max(salary) FROM employees where job_id='IT_PROG') AND job_id<>'IT_PROG';
行子查询(多行多列)
#案例1:查询员工编号最小且工资最高的员工信息
SELECT * FROM employees WHERE employee_id= (SELECT MIN(employee_id) FROM employees) AND salary=(SELECT MAX(salary) FROM employees);
或
SELECT * FROM employees WHERE (employee_id,salary) = (SELECT MIN(employee_id),MAX(salary) FROM employees);(推荐)
SELECT * FROM employees WHERE employee_id= (SELECT MIN(employee_id) FROM employees) AND salary=(SELECT MAX(salary) FROM employees);
或
SELECT * FROM employees WHERE (employee_id,salary) = (SELECT MIN(employee_id),MAX(salary) FROM employees);(推荐)
select后面
#案例1:查询每个部门的员工个数
SELECT d.*,(SELECT COUNT(*) FROM employees e WHERE e.department_id=d.department_id) 个数 FROM departments d;
SELECT d.*,(SELECT COUNT(*) FROM employees e WHERE e.department_id=d.department_id) 个数 FROM departments d;
#案例2:查询员工号=102的部门名
SELECT (SELECT department_name FROM departments d INNER JOIN employees e ON d.department_id=e.employee_id WHERE e.employee_id=102) 部门名;
SELECT (SELECT department_name FROM departments d INNER JOIN employees e ON d.department_id=e.employee_id WHERE e.employee_id=102) 部门名;
from后面(将子查询结果充当一张表,要求必须起别名)
#案例1:查询每个部门的平均工资等级
SELECT a.*,g.grade_level FROM (SELECT AVG(salary) ag,department_id FROM employees GROUP BY department_id) a INNER JOIN job_grades g ON a.ag BETWEEN lowest_sal AND highest_sal;
SELECT a.*,g.grade_level FROM (SELECT AVG(salary) ag,department_id FROM employees GROUP BY department_id) a INNER JOIN job_grades g ON a.ag BETWEEN lowest_sal AND highest_sal;
#案例2:查询各部门中工资比本部门平均工资高的员工的员工号、姓名和工资
SELECT * FROM (SELECT AVG(salary) ag,department_id FROM employees GROUP BY department_id) a INNER JOIN employees e ON a.department_id=e.department_id WHERE salary>a.ag;
SELECT * FROM (SELECT AVG(salary) ag,department_id FROM employees GROUP BY department_id) a INNER JOIN employees e ON a.department_id=e.department_id WHERE salary>a.ag;
exists后面
#案例:查询有员工的部门名
SELECT department_name FROM departments d WHERE EXISTS(SELECT * FROM employees e WHERE d.department_id=e.department_id);
SELECT department_name FROM departments d WHERE EXISTS(SELECT * FROM employees e WHERE d.department_id=e.department_id);
in后面
SELECT department_name FROM departments d WHERE department_id IN (SELECT DISTINCT department_id FROM employees);
分页查询
一页显示不全,需要分页提交sql请求
语法
特点
1、limit语句放在查询语句的最后
2、公式:要显示的页数page,每页的条目数size
2、公式:要显示的页数page,每页的条目数size
select * from table limit (page-1)*size,size;
#案例1:查询前五条的员工信息
SELECT * FROM employees LIMIT 0,5;
SELECT * FROM employees LIMIT 5;
#案例2:有奖金的员工信心,并且工资高的前10名显示出来
SELECT * FROM employees WHERE commission_pct IS NOT NULL ORDER BY salary DESC LIMIT 10;
SELECT * FROM employees WHERE commission_pct IS NOT NULL ORDER BY salary DESC LIMIT 10;
经典例子
查询平均工资最低的部门信息
方式一
①各部门的平均工资
select avg(salary) from employees group by department_id;
②查询①结果上的最低平均工资
select min(ag) from (
select avg(salary) ag,department_id from employees group by department_id
) a;
③查询哪个部门的平均工资=②
select avg(salary),department_id from employees group by department_id
having avg(salary)=(
select min(ag) from (
select avg(salary) ag,department_id from employees group by department_id
) a
)
④查询平均工资最低的部门信息
select * from departments where department_id=(
select avg(salary),department_id from employees group by department_id
having avg(salary)=(
select min(ag) from (
select avg(salary) ag,department_id from employees group by department_id
) a
)
)
select avg(salary) from employees group by department_id;
②查询①结果上的最低平均工资
select min(ag) from (
select avg(salary) ag,department_id from employees group by department_id
) a;
③查询哪个部门的平均工资=②
select avg(salary),department_id from employees group by department_id
having avg(salary)=(
select min(ag) from (
select avg(salary) ag,department_id from employees group by department_id
) a
)
④查询平均工资最低的部门信息
select * from departments where department_id=(
select avg(salary),department_id from employees group by department_id
having avg(salary)=(
select min(ag) from (
select avg(salary) ag,department_id from employees group by department_id
) a
)
)
方式二
①各部门的平均工资
select avg(salary),department_id from employees group by department_id;
②求出最低平均工资的部门编号
select avg(salary),department_id from employees group by department_id
order by avg(salary)
limit 1;
③查询部门信息
select * from departments where department_id=(
select avg(salary),department_id from employees group by department_id
order by avg(salary)
limit 1
);
select avg(salary),department_id from employees group by department_id;
②求出最低平均工资的部门编号
select avg(salary),department_id from employees group by department_id
order by avg(salary)
limit 1;
③查询部门信息
select * from departments where department_id=(
select avg(salary),department_id from employees group by department_id
order by avg(salary)
limit 1
);
联合查询
union 联合 合并:将多条查询语句的结果合并成一个结果
应用场景:要查询的结果来自于多个表,且多个表没有直接的连接关系,但查询的信息一致
应用场景:要查询的结果来自于多个表,且多个表没有直接的连接关系,但查询的信息一致
特点
1、要求多条查询语句的查询列数是一致的
2、要求多条查询语句的每一列的类型和顺序最好一致
3、union关键字默认去重,如果使用union all可以包含重复项
2、要求多条查询语句的每一列的类型和顺序最好一致
3、union关键字默认去重,如果使用union all可以包含重复项
#案例:查询部门编号>90或邮箱包含a的员工信息
方式一:select * from employees where email like '%a%' or department_id>90;
方式二:select * from employees where email like '%a%' union select * from employees where department_id>90
DML
插入
方式一
语法
insert into 表名(字段名,...) values(值,...);
方式二
语法
insert into 表名 set 字段=值,字段=值
修改
修改单表的记录
语法
update 表名 set 字段=值,字段=值 【where 筛选条件】
修改多表的记录
语法
update 表1 别名
left|right|inner join 表2 别名
on 连接条件
set 字段=值,字段=值
【where 筛选条件】
left|right|inner join 表2 别名
on 连接条件
set 字段=值,字段=值
【where 筛选条件】
删除
delete
删除单表的记录
delete from table 【where 筛选条件】
删除多表的记录
delete table1,table2 from table1
inner|left|right join table2
on 连接条件
【where 筛选条件】
【limit 条目数】
inner|left|right join table2
on 连接条件
【where 筛选条件】
【limit 条目数】
truncate
truncate table 表名
两种方式的区别
1.trumcate删除后,如果再插入,标识列从1开始delete删除后,如果再插入,标识列从断点开始
2delete可以添加筛选条件
truncate不可以添加筛选条件
3.trumcate效率较高
4trucate没有返回值
delete可以返回受影响的行数
5.truncate不可以回滚
delete可以回滚
2delete可以添加筛选条件
truncate不可以添加筛选条件
3.trumcate效率较高
4trucate没有返回值
delete可以返回受影响的行数
5.truncate不可以回滚
delete可以回滚
DDL
库的管理
创建库
create database 【if not exists】库名 【chartacter set 字符集名】
修改库
alter database 库名 【chartacter set 字符集名】
删除库
drop database 【if exists】数据库名
表的管理
创建表
create table 【if not exists】表名(
字段名 字段类型 【约束】,
...
)
字段名 字段类型 【约束】,
...
)
修改表
添加列
alter table 表名 add column 列名 类型[first/after 字段名]
修改列的类型或约束
alter table 表名 modify column 列名 新类型【新约束】
修改列名
alter table 表名 change column 日列名 新列名类型
删除列
alter table 表名 drop column 列名;
修改表名
alter table 表名 renane [to] 新表名
删除表
drop table 【if exists】 表名
复制表
表结构复制
create table emp2 like emp;
只复制部分结构
create table emp2 【as】 select id,name from emp where 0;
表结构+数据复制
create table emp30 【as】 select * from emp;
只复制部分结构+数据
create table emp1 as select *from emp where id=101;
数据类型
数值型
整型
分类
tinyint
1
smallint
2
mediumint
3
int/integer
4
bigint
8
特点
1、都可以设置无符号和有符号,默认有符号,通过unsigned设置无符号
2、如果超出了范围,会报out or range异常,插入临界值
3、长度可以不指定,默认会有一个长度
长度代表显示的最大宽度,如果不够则左边用0填充,但需要搭配zerofi11,并且默认变为无符号整型
2、如果超出了范围,会报out or range异常,插入临界值
3、长度可以不指定,默认会有一个长度
长度代表显示的最大宽度,如果不够则左边用0填充,但需要搭配zerofi11,并且默认变为无符号整型
浮点型
定点数
decimal(M,D)
浮点数
float(M,D)
double(M,D)
特点
1、M代表整数部位+小数部位的个数,D代表小数部位
2、如果超出范围,则报out or range异常,并且插入临界值
3、M和D都可以省略,但对于定点数,M默认为10,D默认为0
4、如果精度要求较高,则优先考虑使用定点数
2、如果超出范围,则报out or range异常,并且插入临界值
3、M和D都可以省略,但对于定点数,M默认为10,D默认为0
4、如果精度要求较高,则优先考虑使用定点数
字符型
char、varchar、binary、varbinary、enun、 set、text、blob
char
固定长度的字符,写法为char (m,最大长度不能超过,其中M可以省略,默认为1
varchar
可变长度的字符,写法为varchar(M),最大长度不能超过M,其中不可以省略
日期型
year
date
time
datetime
日期+时间
8
timestamp
日期+时间
4
比较容易受时区、语法模式、版本的影响,更能反映当前时区的真实时间
常见约束
含义
一种限制,用于限制表中的数据,为了保证表中的数据的准确和可靠性
六大约束
NOT NULL
DEFAULT
PRIMARY KEY
可以组合主键,表级约束中primary key(id,name);
UNIQUE
唯一可为空,但是为空也只能一个空
可以组合唯一键
CHECK
MySQL中不支持
FOREIGN KEY
外键,用于限制两个表的关系,保证该字段的值必须来自于主表的关联列的值
1、要求在从表设置外键关系
2、从表的外键列的类型和主表的关系列的类型要求一致或兼容,名称无要求
3、主表的关联列必须是一个key(一般是主键或唯一)
4、插入数据时,先插入主表,再插入从表
5、删除数据时,先删除从表,再删除主表
2、从表的外键列的类型和主表的关系列的类型要求一致或兼容,名称无要求
3、主表的关联列必须是一个key(一般是主键或唯一)
4、插入数据时,先插入主表,再插入从表
5、删除数据时,先删除从表,再删除主表
添加约束的时机
创建表时
create table 表名(
字段名 字段类型 列级约束,
字段名 字段类型,
表级约束
)
字段名 字段类型 列级约束,
字段名 字段类型,
表级约束
)
修改表时
约束的添加分类
列级约束
六大约束语法上都支持,但外键约束无效
语法
alter table 表名 modify column 字段名 字段类型 新约束;
表级约束
除了非空、默认其它都支持
语法
alter table 表名 add 【constraint 约束名】 约束类型(字段名) 【外键的引用】;
创建表时添加约束
添加列级约束
只支持:默认、非空、主键、唯一
create table stu(
id int primary key,
name varchar(20) not null,
gender char(1) check(gender='男' or gender='女'),
seat int unique,
age int default 18,
majorId int references major(id)
)
create table major(
id int primary key,
majorName varchar(20)
)
id int primary key,
name varchar(20) not null,
gender char(1) check(gender='男' or gender='女'),
seat int unique,
age int default 18,
majorId int references major(id)
)
create table major(
id int primary key,
majorName varchar(20)
)
注:此处外键列级约束不生效
注:查询stu所有的索引,包括主键、外键、唯一
show index from stu
添加表级约束
在各个字段的最下面
【constraint 约束名】 约束类型(字段名)
【constraint 约束名】 约束类型(字段名)
create table stu(
id int,
name varchar(20),
gender cahr(1),
seat int,
age int,
majorId int,
constraint pk primary key(id),
constraint uq unique(seat),
constraint ck cheak(gender='男' or gender='女'),
constraint fk_stu_major foreign key(majorId) references major(id)
)
id int,
name varchar(20),
gender cahr(1),
seat int,
age int,
majorId int,
constraint pk primary key(id),
constraint uq unique(seat),
constraint ck cheak(gender='男' or gender='女'),
constraint fk_stu_major foreign key(majorId) references major(id)
)
通用写法
CREATE TARLE IF EXISTS stu(
id INT PRIMARY KEY,
stuname VARCHAR(20)NOT NULL,
sex CHAR(1),
age INT DEFAULT 18
seat INT UNIOUF
majorId INT
CONSTRAINT fk stuinfo major FOREIGN KEY(majorId)REFERENCES major(id)
);
id INT PRIMARY KEY,
stuname VARCHAR(20)NOT NULL,
sex CHAR(1),
age INT DEFAULT 18
seat INT UNIOUF
majorId INT
CONSTRAINT fk stuinfo major FOREIGN KEY(majorId)REFERENCES major(id)
);
修改表时添加约束
#1.添加非室约束
ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20) NOT NULL
ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20) NOT NULL
#2.添加默认约束
ALTER TABLE stuinfo MODIFY COLUMN age INT DEFAULT 18;
ALTER TABLE stuinfo MODIFY COLUMN age INT DEFAULT 18;
#3.添加主键
1、列级约束
ALTER TABLE stu MODIFY COLUMN Id INT PRIMARY KEY:
2、表级约束
ALTER TABLE stu ADD PRIMARY KFY(id):
1、列级约束
ALTER TABLE stu MODIFY COLUMN Id INT PRIMARY KEY:
2、表级约束
ALTER TABLE stu ADD PRIMARY KFY(id):
#4.添加唯一
1、列级约束
ALTER TABLE stu MODIFY COLUMN seat INT UNIQUE
2、表级约束
ALTER TABLE stu ADD UNIQUE (seat) :
1、列级约束
ALTER TABLE stu MODIFY COLUMN seat INT UNIQUE
2、表级约束
ALTER TABLE stu ADD UNIQUE (seat) :
#5.添加外键
alter table stu add constraint fk_stu_major foreign key(majorId) references major(id);
alter table stu add constraint fk_stu_major foreign key(majorId) references major(id);
修改表时删除约束
#1.删除非空约束
ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20) NULL
ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20) NULL
#2.删除默认约束
ALTER TABLE stuinfo MODIFY COLUMN age INT 18;
ALTER TABLE stuinfo MODIFY COLUMN age INT 18;
#3.删除主键
alter table stu drop primary key;
alter table stu drop primary key;
#4.删除唯一
alter table stu drop index seat;
alter table stu drop index seat;
#5.删除外键
alter table stu drop foreign key majorId;
alter table stu drop foreign key majorId;
标识列
又称自增长列
auto_increment
show variables like '%auto_increment%'
设置步长
set auto_increment_increment=3
特点
1、标识列必须为key
2、一个表中最多只有一个标识列
3、标识列的类型只能是数值型
4、标识列可通过set auto_increment_increment=3设置步长
2、一个表中最多只有一个标识列
3、标识列的类型只能是数值型
4、标识列可通过set auto_increment_increment=3设置步长
修改表时设置标识列
alter table tab_identity modify colomn id int primary key auto increment;
修改表时删除标识列
alter table tab_identity modify colomn id int;
TCL
事务控制语言
事务
概念
就是多条DML语句同时成功,或者同时失败。单元中一条sql失败,整个单元回滚
原子性(Atomicity):指事务是一个不可分割的工作单位,事务中的操作要么同成功,要么同失败
一致性(Consistency):事务前后的数据完整性要保证一致,1000
隔离性(Isolation):多用户不相互影响(脏读:一个事务读取了另一个事务未提交的数据)
持久性(Durability):事务一旦提交就不可逆,事务未提交恢复到原装。
一致性(Consistency):事务前后的数据完整性要保证一致,1000
隔离性(Isolation):多用户不相互影响(脏读:一个事务读取了另一个事务未提交的数据)
持久性(Durability):事务一旦提交就不可逆,事务未提交恢复到原装。
拓展
存储引擎
在mysql中的数据用各种不同的技术存储在文件(或内存)中
show engines
mysql中innodb支持事务,myisam和memory不支持
事务的创建
隐式事务:事务没有明显的开启和结束的标记
比如insert、update、delete语句
比如insert、update、delete语句
显式事务:事务具有明显的开启和结束的标记
前提:必须先设置自动提交功能为禁用
前提:必须先设置自动提交功能为禁用
步骤1:开启事务
set autocommit=0(关闭事务自动提交)
start transaction;(可选)
步骤2:编写事务中的sql语句(select insert update delete)
语句1;
语句2;
语句1;
语句2;
步骤3:结束事务
commit;提交事务
rollback【to savepoint】;回滚事务
commit;提交事务
rollback【to savepoint】;回滚事务
事务间的4个隔离级别
1、读未提交:read uncommitted(最低的隔离级别)(很少用这么低的隔离级别)
例:事务A读取到事务B未提交的数据。存在的问题:脏读。
例:事务A读取到事务B未提交的数据。存在的问题:脏读。
2、读已提交:read committed
例:事务A只能读取到事务B提交后的数据。存在的问题:不可重复读取数据。
什么是不可重复读数据?
在事务开启之后,第一次读到的数据是3条,当前事务还未结束,
可能第二次再读取时,读到的数据是4条。
注:第一次读到的数据绝对的真实。是Oracle默认的隔离级别!!!
例:事务A只能读取到事务B提交后的数据。存在的问题:不可重复读取数据。
什么是不可重复读数据?
在事务开启之后,第一次读到的数据是3条,当前事务还未结束,
可能第二次再读取时,读到的数据是4条。
注:第一次读到的数据绝对的真实。是Oracle默认的隔离级别!!!
3、可重复读:repeatable read(提交之后也读不到)(默认)
什么是可重复读数据?
事务A开启后,每一次在事务A中读取到的数据都一致,即使事务B将数据修改,
并且提交了,事务A读取到的数据还是没有发生改变。
可重复读解决了什么问题?
解决了不可重复读取数据的问题。
可重复读存在的问题?
可能会出现幻影读(虚读)。
注:可重复读是MySQL默认的隔离级别!!!
什么是可重复读数据?
事务A开启后,每一次在事务A中读取到的数据都一致,即使事务B将数据修改,
并且提交了,事务A读取到的数据还是没有发生改变。
可重复读解决了什么问题?
解决了不可重复读取数据的问题。
可重复读存在的问题?
可能会出现幻影读(虚读)。
注:可重复读是MySQL默认的隔离级别!!!
4、序列化/串行化:serializable(最高的隔离级别,效率最低,解决了所有问题)
这种隔离级别表示事务排队,不能并发!
类似于synchronize,线程同步(事务同步)
每次读取到的数据都是最真实的,并且效率是最低的。
这种隔离级别表示事务排队,不能并发!
类似于synchronize,线程同步(事务同步)
每次读取到的数据都是最真实的,并且效率是最低的。
语句
MySQL5
select @@tx_isolation
MySQL8
select @@transaction_isolation
set session transaction isolation level read uncommitted;
同时打开两个cmd命令
其一
设置最低隔离级别
select @@transaction_isolation
set session transaction isolation level read uncommitted;
set autocommit=0;
update test.park set name='123' where value=1;
rollback;
重新设置读已提交隔离级别
set session transaction isolation level read committed;
set autocommit=0;
update test.park set name='234' where value=2;
重新设置可重复读隔离级别
set session transaction isolation level repeatable read;
set autocommit=0;
select * from test.park;
update test.park set pk='D';
重新设置序列化/串行化隔离级别
set session transaction isolation level serializable;
set autocommit=0;
update test.park set name='234' where value=2;
其二
对应其一中的隔离级别rollback前后进行查看
select @@transaction_isolation
set session transaction isolation level read uncommitted;
set autocommit=0;
select * from test.park;
对应其一中的读已提交隔离级别进行查看
set session transaction isolation level read uncommitted;
set autocommit=0;
对应其一中的可重复读隔离级别进行查看
set session transaction isolation level read uncommitted;
set autocommit=0;
insert into park values('1','1','1','1','1');
commit;
对应其一中的序列化隔离级别进行查看
set session transaction isolation level serializable;
set autocommit=0;
insert into park values('1','1','1','1','1');
commit;
设置全局隔离级别
set global transaction level read committed;
最好重启下MySQL服务
设置保存点
savepoint a;
delete from emp where id=1;
rollback to a;
视图
含义
虚拟表,和普通表一样使用,是通过表动态生成的数据
特点
重用sql语句
简化复杂的sql操作,不必知道它的查询细节
保护数据,提高安全性
创建视图
引入
查询姓张的学生名和专业名
select stuname,majorname from stu s inner join major m on s.'majorid'=m.'id' where s.'stuname' like '张%';
create view v1
as
select stuname,majorname
from stu s inner join major m on s.'majorid'=m.'id';
select * from v1 where stuname like '张%'
as
select stuname,majorname
from stu s inner join major m on s.'majorid'=m.'id';
select * from v1 where stuname like '张%'
语法
create view 视图名
as
查询语句;
as
查询语句;
案例
#1.查询邮箱中包含a字符的员工名、部门名、工种信息
CREATE VIEW v1
AS
SELECT last_name,department_name,job_title FROM employees e
JOIN departments d ON e.department_id=d.department_id
JOIN jobs j ON j.job_id=e.job_id;
SELECT last_name,department_name,job_title FROM v1 WHERE last_name LIKE '%a%';
CREATE VIEW v1
AS
SELECT last_name,department_name,job_title FROM employees e
JOIN departments d ON e.department_id=d.department_id
JOIN jobs j ON j.job_id=e.job_id;
SELECT last_name,department_name,job_title FROM v1 WHERE last_name LIKE '%a%';
#2.查询各部门的平均工资等级
CREATE VIEW v2
AS
SELECT AVG(salary) ag,department_id FROM employees GROUP BY department_id;
SELECT v2.ag,g.grade_level FROM v2
JOIN job_grades g ON v2.ag BETWEEN g.lowest_sal AND g.highest_sal;
CREATE VIEW v2
AS
SELECT AVG(salary) ag,department_id FROM employees GROUP BY department_id;
SELECT v2.ag,g.grade_level FROM v2
JOIN job_grades g ON v2.ag BETWEEN g.lowest_sal AND g.highest_sal;
#3.查询平均工资最低的部门信息
方式一:
SELECT d.* FROM v2
JOIN departments d ON v2.department_id=d.department_id
WHERE ag = (SELECT MIN(ag) FROM v2)
;
SELECT d.* FROM v2
JOIN departments d ON v2.department_id=d.department_id
WHERE ag = (SELECT MIN(ag) FROM v2)
;
方式二:
SELECT * FROM departments d
WHERE d.department_id=(
SELECT department_id
FROM v2
ORDER BY ag
LIMIT 1);
SELECT * FROM departments d
WHERE d.department_id=(
SELECT department_id
FROM v2
ORDER BY ag
LIMIT 1);
方式三:
CREATE VIEW v3
AS
SELECT * FROM v2 ORDER BY ag LIMIT 1;
SELECT d.*,v3.ag
FROM v3
JOIN departments d
ON v3.department_id=d.department_id;
CREATE VIEW v3
AS
SELECT * FROM v2 ORDER BY ag LIMIT 1;
SELECT d.*,v3.ag
FROM v3
JOIN departments d
ON v3.department_id=d.department_id;
修改视图
引入
CREATE OR REPLACE VIEW v3
AS
SELECT AVG(salary),job_id
FROM employees
GROUP BY job_id;
AS
SELECT AVG(salary),job_id
FROM employees
GROUP BY job_id;
语法
方式一:
create or replace view 视图名
as
查询语句;
create or replace view 视图名
as
查询语句;
方式二:
alter view 视图名
as
查询语句;
alter view 视图名
as
查询语句;
删除视图
语法
drop view v1,v2...;
查看视图
desc v1;
show create view v1;
视图的更新
CREATE OR REPLACE VIEW v1
AS
SELECT last_name,email FROM employees;
INSERT INTO v1 VALUES('kx','187@qq.com');
AS
SELECT last_name,email FROM employees;
INSERT INTO v1 VALUES('kx','187@qq.com');
经过测试,视图的增删改会影响原表的数据,所以会对角色做更新权限设置
具备以下条件的视图不允许更新
1、包含以下关键字的sql语句:分组函数、distinct、group by、having、union或union all
案例:视图创建语句中带有group by,更新错误
CREATE OR REPLACE VIEW v1
AS
SELECT MAX(salary) m,department_id FROM employees GROUP BY department_id;
SELECT * FROM v1;
UPDATE v1 SET m=1000 WHERE department_id=10;
CREATE OR REPLACE VIEW v1
AS
SELECT MAX(salary) m,department_id FROM employees GROUP BY department_id;
SELECT * FROM v1;
UPDATE v1 SET m=1000 WHERE department_id=10;
2、常量视图
CREATE OR REPLACE VIEW v1
AS
SELECT 'jonn' name;
SELECT * FROM v1;
UPDATE v1 SET NAME='kx';
AS
SELECT 'jonn' name;
SELECT * FROM v1;
UPDATE v1 SET NAME='kx';
3、select中包含子查询
4、join
可更新,不能增删
CREATE OR REPLACE VIEW v1
AS
SELECT e.last_name,d.department_name FROM employees e
JOIN departments d
ON e.department_id=d.department_id;
SELECT * FROM v1;
UPDATE v1 SET last_name='kx' WHERE last_name='Whalen';
SELECT * FROM employees WHERE last_name='kx';
DELETE FROM v1 WHERE last_name='kx';
INSERT INTO v1 VALUES('kx','boss');
AS
SELECT e.last_name,d.department_name FROM employees e
JOIN departments d
ON e.department_id=d.department_id;
SELECT * FROM v1;
UPDATE v1 SET last_name='kx' WHERE last_name='Whalen';
SELECT * FROM employees WHERE last_name='kx';
DELETE FROM v1 WHERE last_name='kx';
INSERT INTO v1 VALUES('kx','boss');
视图和表的区别
创建语法的关键字
create view
create table
是否实际占用物理空间
视图只保存了sql逻辑
表保存了数据,占物理空间
视图一般不做增删改
变量
系统变量
说明
变量由系统提供,不是用户定义,属于服务器层面
分类
全局变量
作用域
服务器每次启动将为所有的全局变量赋初始值,针对于所有的会话(连接)有效,但不能跨重启
如果希望每次重启都保存原来的配置,需要调整mysql的配置文件
查看所有的全局变量
show global variables;
查看部分全局变量
show global variables like '%char%';
查看指定的某个全局变量的值
select @@global.autocommit;
select @@global.transaction_isolation;
为某个指定的全局变量赋值
set @@global.autocommit=0;
会话变量
作用域
仅针对于当前会话(连接)有效
查看所有的会话变量
show variables;
show session variables;
show session variables;
查看部分会话变量
show variables like '%char%';
show session variables like '%char%';
show session variables like '%char%';
查看指定的某个会话变量的值
select @@autocommit;
select @@session.transaction_isolation;
为某个指定的全局变量赋值
set @@transaction_isolation='read-committed';
set session transaction_isolation='read-committed'
注:如果是全局级别,则需要加global,如果是会话级别,则需要加session,如果不写,默认session
使用
查看所有的系统变量
show global|session variables;
查看部分系统变量
show global|session variables like '%char%';
查看某个系统变量的值
select @@global|session.系统变量名;
为某个系统变量赋值
方式一:
set global|session 系统变量名=值
set global|session 系统变量名=值
方式二:
set @@global!session.系统变量名=值
set @@global!session.系统变量名=值
自定义变量
说明
变量是用户自定义的,不是由系统的
用户变量
作用域:针对于当前会话(连接)有效,同于会话变量的作用域
应用在任何地方,也就是begin end或begin end外面
应用在任何地方,也就是begin end或begin end外面
声明并初始化
set @用户变量名=值;
set @用户变量名:=值;
select @用户变量名:=值;
set @用户变量名:=值;
select @用户变量名:=值;
赋值
赋值的操作符:"="或":="
方式一:通过set或select
set @用户变量名=值;
set @用户变量名:=值;
select @用户变量名:=值;
set @用户变量名=值;
set @用户变量名:=值;
select @用户变量名:=值;
方式二:通过select into
select 字段 into 变量名 from 表;
select 字段 into 变量名 from 表;
select count(*) into @count from employees;
使用(查看、比较、运算等)
查看用户变量的值
select @用户变量名;
案例
set @m=1;
set @n=2;
set @sum=@m+@n;
select @sum;
set @n=2;
set @sum=@m+@n;
select @sum;
局部变量
作用域:仅定义在它的begin end中有效
应用在begin end中,且为第一句话
应用在begin end中,且为第一句话
声明
DECLARE 变量名 类型;
DECLARE 变量名 类型 DEFAULT 值;
赋值
赋值的操作符:"="或":="
方式一:通过set或select
set 局部变量名=值;
set 局部变量名:=值;
select @局部变量名:=值;
set 局部变量名=值;
set 局部变量名:=值;
select @局部变量名:=值;
方式二:通过select into
select 字段 into 局部变量名 from 表;
select 字段 into 局部变量名 from 表;
使用
select 局部变量名;
案例
declare m int default 1;
declare n int default 2;
declare sum int;
set sum=m+n;
select sum;
declare n int default 2;
declare sum int;
set sum=m+n;
select sum;
存储过程和函数
说明
类似于java中的方法
好处
提高代码的重用性
简化操作
存储过程和函数的区别
存储过程
可以有0个返回,也可以有多个返回,适合批量插入,批量更新
函数
有且仅有1个返回,适合做处理数据后返回的一个结果
存储过程
含义
一组预先编译好的SQL语句的集合,理解成批处理语句
好处
提高代码的重用性
简化操作
减少了编译次数并且减少了和数据库服务器的连接次数,提高了效率
创建存储过程
语法
delimiter $
create procedure 存储过程名(参数列表)
BEGIN
存储过程体(一组合法的SQL语句)
END $
create procedure 存储过程名(参数列表)
BEGIN
存储过程体(一组合法的SQL语句)
END $
参数列表包含三部分
参数模式
IN:该参数可作为输入,即该参数需调用方传入值
OUT:该参数可作为输出,即该参数可作为返回值
INOUT:该参数即可作为输入又可作为输出,即该参数既需要传入值,又可以返回值
参数名
参数类型
如果存储过程仅仅只有一句话,BEGIN END可省略
存储过程体中的每条SQL语句的结尾要求必须加分号
存储过程的结尾可使用DELIMITER重新设置
语法
DELIMITER 结束标记
案例
DELIMITER $
调用存储过程
CALL 存储过程名(实参列表)$
创建空参存储过程
#案例:在admin中插入5行
delimiter $
create procedure p1()
begin
insert into admin(username,password) values('a1','123'),('a2','123'),('a3','123'),('a4','123'),('a5','123');
end $
调用:
call p1()$
delimiter $
create procedure p1()
begin
insert into admin(username,password) values('a1','123'),('a2','123'),('a3','123'),('a4','123'),('a5','123');
end $
调用:
call p1()$
创建带in模式参数的存储过程
#案例:创建存储过程实现根据女神名,查询对应的男神信息
create procedure p2(in beautyName varchar(50))
begin
select bo.* from boys bo right join beauty b on bo.id=b.boyfriend_id where b.name=beautyName;
end $
调用:
call p2('小昭')$
create procedure p2(in beautyName varchar(50))
begin
select bo.* from boys bo right join beauty b on bo.id=b.boyfriend_id where b.name=beautyName;
end $
调用:
call p2('小昭')$
#案例2:创建存储过程实现,用户是否登录成功
create procedure p3(in username varchar(20),in password varchar(20))
begin
declare result int default 0;
select count(*) into result from admin where admin.username=username and admin.password=password;
select if(result>0,'成功','失败');
end $
call p3('a1','111')$
create procedure p3(in username varchar(20),in password varchar(20))
begin
declare result int default 0;
select count(*) into result from admin where admin.username=username and admin.password=password;
select if(result>0,'成功','失败');
end $
call p3('a1','111')$
创建带out模式参数的存储过程
#案例:根据女神名,返回对应的男神名
CREATE PROCEDURE p4(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20))
BEGIN
SELECT bo.boyName INTO boyName FROM boys bo INNER JOIN beauty b ON bo.id=b.boyfriend_id WHERE b.name=beautyName;
END $
#调用
CALL p4('热巴',@bName)$
SELECT @bName$
CREATE PROCEDURE p4(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20))
BEGIN
SELECT bo.boyName INTO boyName FROM boys bo INNER JOIN beauty b ON bo.id=b.boyfriend_id WHERE b.name=beautyName;
END $
#调用
CALL p4('热巴',@bName)$
SELECT @bName$
#案例2:根据女神名,返回对应的男神名和男神魅力值
CREATE PROCEDURE p5(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20),OUT userCP int)
BEGIN
SELECT bo.boyName,bo.userCP INTO boyName,userCP FROM boys bo INNER JOIN beauty b ON bo.id=b.boyfriend_id WHERE b.name=beautyName;
END $
#调用
CALL p5('小昭',@bName,@usercp)$
CREATE PROCEDURE p5(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20),OUT userCP int)
BEGIN
SELECT bo.boyName,bo.userCP INTO boyName,userCP FROM boys bo INNER JOIN beauty b ON bo.id=b.boyfriend_id WHERE b.name=beautyName;
END $
#调用
CALL p5('小昭',@bName,@usercp)$
创建带inout模式参数的存储过程
#案例:传入a和b两个值,最终a和b都翻倍并返回
create procedure p6(inout a int,inout b int)
begin
set a=a*2;
set b=b*2;
end $
#调用
set @m=1$
set @n=2$
call p6(@m,@n)$
select @m,@n$
create procedure p6(inout a int,inout b int)
begin
set a=a*2;
set b=b*2;
end $
#调用
set @m=1$
set @n=2$
call p6(@m,@n)$
select @m,@n$
删除存储过程
drop procedure 存储过程名(一次只能删除一个)
查看存储过程的信息
show create procedure p2;
案例
#1、创建存储存储过程或函数实现传入两个女神生日,返回大小
CREATE PROCEDURE p1(IN birthl DATETIME,IN birth2 DATETIME,OUT result INT)
BEGIN
SELECT DATEDIFF(birthl,birth2)INTO result;
END $
CREATE PROCEDURE p1(IN birthl DATETIME,IN birth2 DATETIME,OUT result INT)
BEGIN
SELECT DATEDIFF(birthl,birth2)INTO result;
END $
#2、创建存储过程或函数实现传入一个日期,格式化成xx年xx月xx日并返回
CREATE PROCEDURE p2(IN mydate DATETIME,OUT StrDate VARCHAR(50))
BEGIN
SELECT DATE FORMAT(mydate,'%y年m月d日") INTO strDate;
END $
CALI p2(NOW(),@str)$
SELECT @str $
CREATE PROCEDURE p2(IN mydate DATETIME,OUT StrDate VARCHAR(50))
BEGIN
SELECT DATE FORMAT(mydate,'%y年m月d日") INTO strDate;
END $
CALI p2(NOW(),@str)$
SELECT @str $
#3、创建存储过程或函数,根据传入的条目数和起始索引,查询beauty表的记录
CREATE PROCEDURE p3(IN startIndex INT,IN size INT)
BEGIN
SELECT * FROM beauty LIMIT startIndex,size;
END $
CALL p3(3,5)$
CREATE PROCEDURE p3(IN startIndex INT,IN size INT)
BEGIN
SELECT * FROM beauty LIMIT startIndex,size;
END $
CALL p3(3,5)$
函数
含义
一组预先编译好的SQL语句的集合,理解成批处理语句
特点
提高代码的重用性
简化操作
减少编译次数并减少了和数据库服务器的连接次数,提高了效率
创建函数
语法
create function 函数名(参数列表) returns 返回类型
begin
函数体
end
begin
函数体
end
参数列表包含两部分
参数名
参数类型
函数体
会有return语句,如果没有会报错,如果return语句没有放在函数体的最后也不报错,但不建议
...
return 值;
return 值;
函数体中仅有一句话可省略begin end
使用delimiter语句设置结束标记
调用函数
语法
select 函数名(参数列表)
要放松函数创建的前述条件,全局系统变量需要设置为1
SET GLOBAL log_bin_trust_function_creators = 1;
无参有返回
#案例:返回公司的员工个数
CREATE FUNCTION f1() RETURNS INT
BEGIN
DECLARE c INT DEFAULT 0; #定义局部变量
SELECT COUNT(*) INTO c FROM employees;
RETURN c;
END $
#调用
select f1()$
CREATE FUNCTION f1() RETURNS INT
BEGIN
DECLARE c INT DEFAULT 0; #定义局部变量
SELECT COUNT(*) INTO c FROM employees;
RETURN c;
END $
#调用
select f1()$
有参有返回
#案例:根据员工名,返回他的工资
CREATE FUNCTION f2(empName VARCHAR(20)) RETURNS INT
BEGIN
SET @sal=0; #定义用户变量
SELECT salary INTO @sal FROM employees WHERE last_name=empName;
RETURN @sal;
END $
#调用
SELECT f2('Ande')$
CREATE FUNCTION f2(empName VARCHAR(20)) RETURNS INT
BEGIN
SET @sal=0; #定义用户变量
SELECT salary INTO @sal FROM employees WHERE last_name=empName;
RETURN @sal;
END $
#调用
SELECT f2('Ande')$
查看函数
select create function f3;
删除函数
drop function f3;
流程控制结构
顺序结构
程序从上往下依次执行
分支结构
含义
程序从两条或多条路径中选择一条去执行
分类
if函数
功能
实现简单的双分支
语法
if(表达式1,表达式2,表达式3)
执行顺序:
如果1成立,则返回2的值,否则返回3的值
执行顺序:
如果1成立,则返回2的值,否则返回3的值
case结构
情况一
类似于java中switch,一般用于实现等值判断
语法
case 变量|表达式|字段
when 要判断的值 then 返回值1或语句1
when 要判断的值 then 返回值2或语句2
...
else 要返回的值n
end
when 要判断的值 then 返回值1或语句1
when 要判断的值 then 返回值2或语句2
...
else 要返回的值n
end
情况二
类似于java中的多重if语句,一般用于实现区间判断
语法
case
when 要判断的条件1 then 返回值1或语句1
when 要判断的条件2 then 返回值2或语句2
..
else 要返回的值n或语句n
end
when 要判断的条件1 then 返回值1或语句1
when 要判断的条件2 then 返回值2或语句2
..
else 要返回的值n或语句n
end
特点
可作为表达式,嵌套在其他语句中使用,可放在任何地方,begin end中或者begin end 外
可作为独立的语句去使用,只能放在begin end中
如果when中的值或条件成立,则执行对应的then后面的语句,并结束case;如果都不满足,则执行else中的语句或值
else可省略,如果else省略了,并且所有when条件都不满足,则返回null
#案例
#创建存储过程,根据传入的成绩,来显示等级,比如传入的成绩:90-100,显示A,80-90,显示B,60-80,显示c,否则,显示D
create procedure p1(in score int)
begin
case
when score>=90 and score<=100 then select 'A';
when score>=80 then select 'B';
when score>=60 then select 'C';
else select 'D';
end case;
end $
#创建存储过程,根据传入的成绩,来显示等级,比如传入的成绩:90-100,显示A,80-90,显示B,60-80,显示c,否则,显示D
create procedure p1(in score int)
begin
case
when score>=90 and score<=100 then select 'A';
when score>=80 then select 'B';
when score>=60 then select 'C';
else select 'D';
end case;
end $
if结构
功能
实现多重分支
语法
功能:买现多重分支
语法:
if 条件1 then 语句1;
elseif 条件2 then 语句2;
【else 语句n;】
end if;
应用在begin end中
语法:
if 条件1 then 语句1;
elseif 条件2 then 语句2;
【else 语句n;】
end if;
应用在begin end中
循环结构
程序在满足一定条件的基础上,重复执行一段代码,都在begin end中
分类
while
语法
【标签:】while 循环条件 do
循环体
end while【标签】;
循环体
end while【标签】;
特点
先判断后执行
loop
语法
【标签:】loop循环体;
end loop【标签】;
可以用来模拟简单的死循环
end loop【标签】;
可以用来模拟简单的死循环
特点
没有条件的死循环
repeat
语法
【标签:】repeat
循环体;
until结刺循环的条件
end repeat【标签】;
循环体;
until结刺循环的条件
end repeat【标签】;
特点
先执行后判断
循环控制
iterate类似于continue,继续,结束本次循环,继续下一次
leave类似于break,跳出,结束当前所在的循环
案例
1、没有添加循环控制语句
#案例:批量插入,根据次数插入到admin表中多条记录
CREATE PROCEDURE p7(IN insertCount INT)
BEGIN
DECLARE i INT DEFAULT 1;
while i<=insertCount DO
INSERT INTO admin(username,PASSWORD) VALUES(CONCAT('kx',i),'111');
SET i=i+1;
END while;
END $
BEGIN
DECLARE i INT DEFAULT 1;
while i<=insertCount DO
INSERT INTO admin(username,PASSWORD) VALUES(CONCAT('kx',i),'111');
SET i=i+1;
END while;
END $
2、添加leave语句
#案例:批量插入,根据次数插入到admin表中多条记录,如果次数>20就停止
CREATE PROCEDURE p8(IN insertCount INT)
BEGIN
DECLARE i INT DEFAULT 1;
a:while i<=insertCount DO
INSERT INTO admin(username,PASSWORD) VALUES(CONCAT('kx',i),1000);
if i>=20 then leave a;
END if;
SET i=i+1;
END while a;
END $
BEGIN
DECLARE i INT DEFAULT 1;
a:while i<=insertCount DO
INSERT INTO admin(username,PASSWORD) VALUES(CONCAT('kx',i),1000);
if i>=20 then leave a;
END if;
SET i=i+1;
END while a;
END $
3、添加iterate语句
#案例:批量插入,根据次数插入到admin表中多条记录,只插入偶数次
CREATE PROCEDURE p9(IN insertCount INT)
BEGIN
DECLARE i INT DEFAULT 0;
a:while i<=insertCount DO
SET i=i+1;
if MOD(i,2)!=0 then iterate a;
END if;
INSERT INTO admin(username,PASSWORD) VALUES(CONCAT('kx',i),1000);
END while a;
END $
BEGIN
DECLARE i INT DEFAULT 0;
a:while i<=insertCount DO
SET i=i+1;
if MOD(i,2)!=0 then iterate a;
END if;
INSERT INTO admin(username,PASSWORD) VALUES(CONCAT('kx',i),1000);
END while a;
END $
0 条评论
下一页