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