B站MySQL(尚硅谷)学习笔记

B站MySQL基础(尚硅谷)学习笔记

最近在学习数据库技术,并且把视频中的知识点进行了汇总,字数较多,仅供参考。
会持续更新
欢迎读者提出问题与错误,一起交流~

视频前几集所讲述的基本知识:

  1. DB:数据库,保存一组有组织的数据的容器。

    DBMS:数据库管理系统:又称为数据库软件(产品),用于管理DB中的数据。

    SQL:结构化查询语言,用于和DBMS通信的语言。

  2. 将数据先放到表里面,再把表放到库里。

    一个数据库中可以有多张表,每个表都有一个的名字,用来标识自己,表名具有唯一性。

    表具有一些特性,这些特性定义了数据在表中如何存储,类似java中类的设计。

    表由列组成,我们也称为字段,所有表都是由一个或者多个列组成的,每一个列类似于Java中的属性。

  3. MySQL不区分大小写,但建议关键字大写,表名,列名小写。

    每条命令最好用分号结尾。

    每条命令根据需要,可以进行缩进和换行。

  4. 注释:单行注释: # 注释文字 单行注释: – 注释文字 多行注释: /* 645465 */

  5. DQL语言的学习(数据查询语言)(针对于查询(select))

    DML语言的学习(数据操作语言)(针对于增删改)

    DDL语言的学习(数据定义语言)(针对库和表的定义,创建删除等)

    TCL语言的学习(事物控制语言)

  6. DQL学习

进阶一:基础查询

select 查询列表 from 表名;

类似于: System.out.println(‘’打印的东西‘’);

特点:查询列表可以是:表中的字段、常量值、表达式、函数。查询的结果是一个虚拟的表格。

1.查询表中的单个字段

SELECT last_name FROM employees;

2.查询表中的多个字段

SELECT last_name,salary,email FROM employees;

3.查询表中的所有字段

SELECT * FROM employees;

4.查询常量值

SELECT 100;

SELECT 'john';

5.查询表达式

SELECT 100*98;

SELECT 100%98;

6.查询函数

SELECT VERSION();

7.起别名

1.便于理解。

2.如果要查询的字段有重名的情况,使用别名可以区分开来

方式一

SELECT 100%98 AS 结果;

SELECT last_name AS 姓,first_name AS 名 FROM employees;

方式二

SELECT last_name 姓, first_name 名 FROM employees;

案例:查询salary ,显示结果是 out put。

SELECT salary AS "OUT put" FROM employees;

8.去重

里面只可以放一个

案例 :查询员工表中涉及到的所有部门编号

SELECT DISTINCT department_id FROM employees;

9.+号的作用

java中的+号作用

1.运算符(数值型)

2.连接符,只要有一个操作数为字符串。

mysql中的+号只有一个功能:运算符

select 100+90;

两个操作数都是数值型,则做加法

select '123'+90;(为90)

其中一方为字符型,试图将字符型数值转换为数值型

如果转换成功,就继续左加法运算。如果转换失败,则将字符型数值转换成0

select null+10;为null

案例:查询员工名和姓链接成一个字段,并显示为姓名

SELECT 

		CONCAT(last_name,first_name) AS 姓名 

FROM
		employees;

10.` 的作用

着重号,用于区分NAME(关键字)和NAME(表内容)的区别。

建议还是不要使用 ,当需要命名name时,可以将name前面加上一些别的字母,用来于关键字区别。

如:s_name,t_name 等。

进阶二:条件查询

语法:

select 
		查询列表
from
		表名
where
	    筛选条件;

分类:

一、按条件表达式筛选

条件运算符: > < =(等于) <>(不等) >= <=

案例一:查询工资大于12000的员工。

SELECT * FROM employees WHERE salary>12000 ;

案例二:查询部门编号不等于90号的员工名和部门编号。

SELECT 
		last_name , department_id 
FROM 
		employees
WHERE
		department_id<>90;
		# 或者 department_id!=90

二、按逻辑表达式筛选

作用:用于连接条件表达式

逻辑运算符 : && || !

推荐:and or not

案例一:查询工资在10000-20000之间的员工名、工资以及奖金。

 SELECT 
 		last_name,salary,commission_pct
 FROM 
 		employees  
 WHERE 
 		salary>=10000&&salary<=20000;
 		#或者用and

案例二:查询部门编号不是在90-110之间,或者工资大于15000的员工信息。

 SELECT 
 		* 
 FROM 
 		employees  
 WHERE 
 		department_id > 110 or department_id< 90 OR salary>15000;

或者:

SELECT 
		* 
FROM 
		employees 
WHERE 
		NOT(department_id>=90 AND department_id<=110) OR salary>15000; 

三、模糊查询

like、between and、in、is null

like

特点:一般和通配符搭配使用

通配符:

% 任意多个字符(包含零个)

_ 任一单个字符

案例一:查询员工名中包含字符a的员工信息。

 SELECT 
 		* 
 FROM 
 		employees  
 WHERE 
 		last_name LIKE '%a%' ;

案例二:查询员工中第三个字符为e,第五个字符为a的员工名和工资。

SELECT 
		last_name,salary
FROM
		employees
WHERE
		last_name LIKE '___e_a%';

案例三:查询员工名中第二个字符为下划线的员工名。

SELECT 
		last_name
FROM
		employees
WHERE
		last_name LIKE '_\_%';

between and

使用between and可以提高语句的简洁度,包含两个临界值,两个临界值不要颠倒顺序。

案例一:查询员工编号在100-120之间的员工信息。

SELECT 
		*
FROM
		employees
WHERE
		employee_id BETWEEN 100 AND  120; 

in

含义:判断某字段的值是否属于in列表中的某一项。

特点:1.使用in提高语句简洁度。

​ 2.in列表的值类型必须统一或者兼容。

案例一:查询员工的工种编号是IT_RPOG、AD_VP、AD_PRES中的一个员工名和工种编号

SELECT 
		last_name,job_id
FROM
		employees
WHERE
		job_id IN ('IT_RPOG','AD_VP','AD_PRES');

is null

案例一:查询到没有奖金的员工和奖金率。

SELECT
		last_name,commission_pct
FROM
		employees
WHERE
		commission_pct IS NOT NULL;

<=>

安全等于:相当于是否等于

案例一:

SELECT
		last_name,commission_pct
FROM
		employees
WHERE
		commission_pct <=>NULL;

B站MySQL(尚硅谷)学习笔记_第1张图片

前几节课总结

数据库相关概念

一、数据库的好处

1.可以持久化数据到本地。

2.结构化查询。

二、数据库的常见概念

1.DB:数据库。

2.DBMS:数据库管理系统,又称为数据库软件或者数据库产品,用于创建或者管理DB。

3.SQL:结构化查询语言,用于和数据库通信的语言,不是某个软件所特有的,是都用这个。

三、数据库存储数据的特点

1.数据存放到表中,然后表再放到库中。

2.一个库中可以有多张表,每张表具有唯一的表名来标识自己。

3.表中有一个或者多个列,列又称为字段,相当于Java中的属性。

4.表中的每一个数据,相当于Java中的对象 。

四、常见的数据库管理系统

MySQL oracle db2 sqlserver

进阶三:排序查询

语法:

SELECT 
 		查询列表
FROM
		表
【WHERE  筛选条件】
ORDER BY 排序列表  【asc|desc】
ASC从低到高(不填默认为升序)  desc从高到低	
ORDER BY 子句中可以支持单个字段、多个字段、表达式、函数、别名
ORDER BY 子句一般放在查询语句的最后面,除了limit子句。

注:【】表示可以有也可以无

案例一:查询员工信息。要求工资从高到低排序、从低到高。

SELECT 
		* 
FROM 
		employees 
ORDER BY 
		salary DESC;
		
		
SELECT 
		* 
FROM 
		employees 
ORDER BY 
		salary ;

案例二:查询部门编号>=90的员工信息,按入职时间的先后顺序进行排序。

SELECT 
		*
FROM 
		employees
WHERE  
		department_id>=90
ORDER BY 
		hiredate ASC;

案例三:【按表达式排序】 按年薪的高低显示员工的信息和年薪。

SELECT 
		* ,salary*12*(1+IFNULL(commission_pct,0)) #年薪
FROM 
		employees
ORDER BY 
		salary*12*(1+IFNULL(commission_pct,0)) DESC;
#利用别名更好  
ORDER BY 年薪 DESC;

案例四:按姓名的长度显示员工的姓名和工资【按函数排序】。

SELECT
		LENGTH(last_name) 字节长度,last_name,salary
FROM 
		employees
ORDER BY 
		LENGTH(last_name) DESC;

案例五:查询员工信息,要求先按工资升序,再按员工编号降序【按多个字段排序】。

SELECT	
		*
FROM 
		employees
ORDER BY 
		salary ASC,employee_id DESC;

进阶四:函数

功能:类似于Java的方法,将一组逻辑语句封装在方法中,对外暴露方法名。

好处:

1.隐藏了实现细节 。

2.提高代码的重用性 。

调用:

SELECT 函数名(实参列表) 【FROM 表】;

特点:1.函数名 2.函数功能

分类:

1.单行函数 如:CONCAT length IFNULL

2.分组函数:又称为统计函数,聚合函数,组函数 用于统计使用

1.字符函数

length:获取子节个数

SELECT LENGTH('jack');

SELECT LENGTH('哈哈哈');# 一个汉字是三个子节

concat:拼接字符串

SELECT 
		CONCAT(last_name,'_',first_name) 
FROM 
		employees;

upper、lower: 大小写转换

SELECT UPPER('ohhh');

SELECT LOWER('DADASDA');

实例:将姓变成大写,名变成小写

SELECT
		CONCAT(UPPER(last_name),LOWER(first_name)) 姓名 
FROM 
		employees;

SUBSTR、 SUBSTRING: 字符串裁剪

注意:索引是从1开始的

案例:截取从指定索引处后面的所有字符

SELECT SUBSTR('李莫愁爱上了路展元',7) out_put;#输出路展元

案例:截取从指定索引处指定字符长度的字符

SELECT SUBSTR('李莫愁爱上了路展元',1,3) out_put;#输出李莫愁

案例:姓名中首字符大写,其他字符小写然后用_拼接,显示出来

SELECT
		CONCAT(UPPER(SUBSTR(last_name,1,1)),'_',LOWER(SUBSTR(last_name,2)))  out_put 
FROM 
		employees;

INSTR: 返回子串第一次出现的索引,如果找不到返回0

SELECT INSTR('杨不悔爱上了印巴下','印巴下') AS out_put;

trim :去掉前后的空格或者指定的字符

SELECT LENGTH(TRIM(' 张翠山 ')) AS out_put;
SELECT TRIM('a' FROM'aaaaaaaaa大aaa旭aaaaa') AS out_put;

lpad: 用指定的字符实现左填充指定长度

SELECT LPAD('畅',5,'#');

rpad: 右填充

SELECT RPAD('畅',5,'@');

replace :替换

SELECT REPLACE('Java畅学Java','Java','SQL');

2.数学函数

round:四舍五入

SELECT ROUND(1.55);#1.6

SELECT ROUND(1.567,2);#1.57

ceil :向上取整

返回>=该参数的最小整数

SELECT CEIL(1.02);#2

floor: 向下取整

SELECT FLOOR(5.01);#5

truncate:截断

SELECT TRUNCATE(1.66,1);# 1.6

mod:取余

mod(a,b)相当于a-a/b×b

SELECT MOD(10,3);

3.日期函数

now 返回当前系统日期+时间

SELECT NOW();

可以获取指定的部分,年月日小时分钟秒

SELECT YEAR(NOW()) 年;

SELECT YEAR('2001-05-03') 年;

curdate 返回日期不含时间

SELECT CURDATE();

curtime 返回时间不返回日期

SELECT CURTIME();

str_to_date 将字符通过指定格式转换成日期

SELECT STR_TO_DATE('1998-3-2','%Y-%c-%d')AS out_put;

4.流程控制函数

1.if函数:

if else效果

SELECT IF(10>4,'大','小');

SELECT last_name,commission_pct,IF(commission_pct IS NULL,'呜呜','哈哈') FROM employees;

2.case函数:

1 :与switch case 一样的效果

case 要判断的字段或表达式

when 常量1 then 要显示的值或者语句1

when 常量1 then 要显示的值或者语句2    

....

else 要显示的值或者语句n;

end

2:类似于多重if

case

when 条件一 then 要显示的值或者语句

when 条件二 then 要显示的值或者语句

 ...

else 要显示的值或者语句

end  

案例: 显示不同编号的不同工资

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 AS 新工资

FROM employees;

案例二 :查询员工工资情况, 如果大于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;

5. 分组函数

分类:sum求和,avg平均,max,min,count(计算个数)

USE myemployees;

SELECT SUM(salary) 和 FROM employees;

SELECT AVG(salary) 平均 FROM employees;

SELECT MAX(salary) 最大 FROM employees;

SELECT MIN(salary) 最小 FROM employees;

SELECT COUNT(salary) 总计 FROM employees;

参数支持哪些类型

SELECT SUM(last_name), AVG(last_name) FROM employees;# sum和avg不支持字符/日期

忽略null

和distinct搭配

SELECT SUM(DISTINCT salary), SUM(salary) FROM employees;

SELECT COUNT(DISTINCT salary),COUNT(salary) FROM employees;

count 函数详细介绍

SELECT COUNT(*) FROM employees; # 显示行数

SELECT COUNT(1) FROM employees; # 显示行数 多加一列常量值,用来统计个数

效率

MYISAM 存储引擎下,count(*) 的效率最高

INNODB存储引擎下, count(*) 和 count(1)的效率差不多 ,比count(字段)效率高

进阶五:分组查询

语法: 

SELECT 
 		分组函数,列(要求出现在group by的 后面)

from 
 		表

【WHERE 筛选条件】

GROUP BY 
		分组的列表

【order by 子句】    

查询列表比较特殊:要求是分组函数和group by后出现的字段

特点:

1.分组查询中的筛选条件分为两类

数据源 位置 关键字
分组前筛选 原始表 group by 前面 WHERE
分组后筛选 分组后的结果集 group by后面 having

分组函数做条件肯定放在having子句中

能用分组前筛选的,就优先使用

2.GROUP BY 子句支持单个字段分组,也支持多个字段分组(多个字段)

3.也可以添加排序(排序放在整个分组查询的最后)

案例:查询每个工种的最高工资

SELECT 
		MAX(salary),job_id 
FROM 
		employees

GROUP BY 
		job_id;

案例:查询每个位置上的部门个数

SELECT 
		COUNT(*), location_id

FROM 
		departments

GROUP BY 
		location_id;

添加筛选条件

案例1:查询邮箱中包含字符a的,每个部门的平均工资

SELECT 
		AVG(salary),department_id

FROM 
		employees

WHERE 
		email like '%a%'

GROUP BY
		department_id;

案例2:查询有奖金的每个领导手下员工的最高工资

SELECT 
		MAX(salary),manager_id 

FROM 
		employees

WHERE 
		commission_pct is NOT NULL

GROUP BY 
		manager_id;

添加复杂的筛选条件

案例1:查询哪个部门的员工个数>2

#拆分为两步:

1.查询每个部们的员工个数

2.根据1的去筛选哪个部门的员工个数>2

SELECT 
		count(*),department_id

FROM 
		employees

GROUP BY 
		department_id    

HAVING 
		count(*)>2;

案例2:查询每个工种有奖金的员工的最高工资>12000的工种编号和最高工资

SELECT
		MAX(salary),job_id

FROM 
		employees

WHERE 
		commission_pct is NOT NULL

GROUP BY
		job_id

HAVING 
		MAX(salary)>12000;

案例3:查询领导编号大于102的每个领导手下的最低工资>5000的领导编号是哪个

SELECT 
		MIN(salary),manager_id

FROM 
		employees

WHERE 
		manager_id>102

GROUP BY 
		manager_id

HAVING 
		MIN(salary)>5000;

按表达式(函数)分组

案例:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数>5的有哪写

1.查询每个长度的员工个数

SELECT 
		COUNT(*),LENGTH(last_name) len_name

FROM 
		employees

GROUP BY 
		LENGTH(last_name);

2.添加筛选条件

SELECT 
		COUNT(*),LENGTH(last_name) len_name

FROM 
		employees

GROUP BY 
		LENGTH(last_name)

HAVING 
		COUNT(*)>5;

按多个字段分组

案例:查询每个部门每个工种的员工的平均工资

SELECT 
		AVG(salary),department_id,job_id

FROM 
		employees

GROUP BY 
		department_id,job_id;

添加排序

案例:查询每个部门每个工种的员工的平均工资 ,并且按平均工资的高低显示

SELECT 
		AVG(salary),department_id,job_id

FROM 
		employees

GROUP BY 
		department_id,job_id

ORDER BY 
		AVG(salary) DESC;

进阶六:连接查询

又称为多表查询,当查询的字段来自于多个表时,就会用到连接查询

笛卡尔乘积现象:表1 有m行 表2有n行 ,结果有m*n行

发生原因:没有有效的连接条件

如何避免:添加有效的连接条件

分类:

按年代分类:

sq192标准:仅仅支持内连接

sq199标准:【推荐】 就不支持全外连接

按功能分类:

内连接:等值连接、非等值连接、自连接

外连接:左外连接、右外连接、全外连接、交叉连接

1.sql92标准

等值连接

1.等值连接的结果为多表的交集部分。

2.n表连接至少需要n-1个连接条件。

案例一:查询女神名和对应的男神名

SELECT
		NAME,boyName 
FROM 
		boys,beauty
WHERE 
		beauty.boyfriend_id =boys.id;

案例二:查询员工名和对应的部门名

SELECT 
		last_name, department_name

FROM 
		employees,departments

WHERE 
		employees.department_id=departments.department_id;

为表起别名

提高语句的简洁度,区别多个重名字段 (如果为表起了别名,查询时就不可以再用以前的表名了)

查询员工名,工种号,工种名

SELECT 
		last_name,e.job_id,job_title

FROM
		employees e ,jobs j

WHERE 
		e.job_id =j.job_id;

可以加筛选

案例:查询有奖金的员工名和部门名

SELECT 
		last_name,department_name,e.commission_pct

FROM 
		employees e,departments d

WHERE 
		e.department_id=d.department_id

AND 
		e.commission_pct is NOT NULL; 

案例2:查询城市名中第二个字符为‘o’的部门名和城市名

SELECT 
		department_name,city

FROM 
		departments d,locations l

WHERE 
		d.location_id=l.location_id

AND 
		city LIKE '_o%';

可以加分组

案例1.查询每个城市的部门个数

SELECT 
		COUNT(*) 个数,city

FROM 
		departments d,locations l

WHERE 
		d.location_id=l.location_id

GROUP BY 
		city;

案例2.查询有奖金的每个部门的部门名和部门的领导编号和该部门最低工资

SELECT 
		MIN(salary),d.manager_id,d.department_name

FROM 
		departments d ,employees e

WHERE 
		d.department_id=e.department_id

AND 
		e.commission_pct is NOT NULL

GROUP BY 
		department_name,d.manager_id;

可以加排序

案例:查询每个工种的工种名和员工的个数,并且按员工个数降序

SELECT 
		job_title,COUNT(*)

FROM 
		jobs j,employees e

WHERE 
		j.job_id=e.job_id

GROUP BY 
		job_title

ORDER BY 
		COUNT(*) DESC;

三表连接

案例:查询员工名、部门名、和所在城市名

SELECT 
		last_name,department_name,city

FROM
		employees e,departments d,locations l

WHERE 
		e.department_id=d.department_id

AND 
		d.location_id=l.location_id

ORDER BY
		department_name DESC; 

非等值连接

案例1:查询员工的工资和工资级别

SELECT 
		salary,grade_level

FROM 
		employees e,job_grades j

WHERE 
		salary BETWEEN j.lowest_sal AND j.highest_sal;

自连接

案例:查询 员工名和上级的名称

SELECT 
		e.employees_id,e.last_name,m.employees_id,m.last_name

FROM 
		employees e,employees m

WHERE 
		e.manager_id = m.employee_id;

2.sql99语法

内连接:INNER

外连接

1.左外:left

2.右外:right

3.全外:full

交叉连接:cross

语法:

 SELECT
 		查询列表

 from 
 		表1 别名【连接类型】

 join   表2 别名

 on     连接条件

 【where筛选条件】

 【group by分组】

 【having 筛选    条件】

 【order by 排序列表】

内连接

语法:

SELECT 
		查询列表

from 
		表1 别名

inner join 
		表二 别名
on 
		连接条件;

分类:等值、非等值、自连接

特点:

1.inner可以省略

2.添加排序、分组和筛选

3.筛选条件放在where后面,连接条件放在了on后面、提高了分离性,便于阅读。

等值连接

查询员工名、部门名

SELECT     
		last_name,department_name
		
FROM 
		employees e
		
INNER JOIN
		departments d
		
ON 
		e.department_id =d.department_id;

案例2:查询名字中包含e的员工名和工种名(添加筛选)

SELECT
		last_name,job_title

FROM 
		employees e

INNER JOIN    
		jobs j

ON 
		e.job_id=j.job_id

WHERE
		e.last_name like '%e%';

案例3:查询部门个数 >3的城市名和部门个数,(添加分组和筛选)

SELECT
		city,COUNT(*)

FROM 
		departments d

INNER JOIN 
		locations l

on 
		d.location_id= l.location_id

GROUP BY
		city

HAVING 
		COUNT(*)> 3;

案例4:查询哪个部门的员工个数>3的部门名和员工个数,并按个数降序(添加排序)

1:查询每个部门的员工个数

SELECT
		COUNT(*) ,department_name

FROM 
		employees e

INNER JOIN
		departments d

ON 
		e.department_id=d.department_id

GROUP BY
		department_name;

2:在1的基础上筛选个数大于三的并记录

SELECT 
		COUNT(*) ,department_name

FROM 
		employees e

INNER JOIN 
		departments d

ON 
		e.department_id=d.department_id

GROUP BY 
		department_name

HAVING 
		COUNT(*)>3

ORDER BY
		COUNT(*) DESC;

案例五:查询员工名,部门名,工种名,并按部门名称降序()

SELECT    
		last_name,department_name,job_title

FROM 
		employees e

INNER JOIN
		departments d on e.department_id=d.department_id

INNER JOIN
		jobs j ON j.job_id=e.job_id

ORDER BY 
		department_name  DESC;

非等值连接

查询员工的工资级别

SELECT     
		salary,grade_level

FROM 
		employees e

JOIN    
		job_grades g

ON
		e.salary BETWEEN g.lowest_sal AND g.highest_sal;

查询公司级别个数大于20,并按工资级别降序

SELECT 
		COUNT(*) ,grade_level

FROM 
		employees e

JOIN 
		job_grades g

on 
		e.salary BETWEEN     g.lowest_sal AND g.highest_sal

GROUP BY
		grade_level

HAVING 
		COUNT(*)>20

ORDER BY
		grade_level DESC

自连接

查询员工的名字,上级的名字

SELECT
		e.last_name,m.last_name

FROM 
		employees e

JOIN 
		employees m

ON 
		e.manager_id=m.employee_id;

查询姓名中包含k的员工的名字,上级的名字

SELECT 
		e.last_name,m.last_name

FROM 
		employees e

JOIN 
		employees m

ON 
		e.manager_id=m.employee_id

WHERE 
		e.last_name LIKE '%k%';

外连接

应用场景:查询一个表中有,另一个表中没有的记录

特点:1.外连接的查询结果为主表中的所有记录,如果从表中有和它匹配的,则显示匹配的值。如果没有匹配的,则显示null。

外连接的查询结果=内连接结果+主表中有而从表中没有的记录

2.左外连接,left join左边的是主表。

右外连接,left join右边是主表。

3.左外和右外如果交换两表顺序,可以实现同样的效果

4.全外连接=内连接中结果+表1中没有表2中有的+表1中有表2中没有

案例引入:查询男朋友,不在男神表中的女神名

左外连接

SELECT     
		b.name,bo.*

FROM 
		beauty b

LEFT OUTER JOIN 
		boys bo

ON 
		b.boyfriend_id=bo.id

WHERE 
		bo.id is NULL;

右外连接

SELECT     
		b.name,bo.*

FROM 
		boys bo

RIGHT OUTER JOIN 
		beauty b

ON 
		b.boyfriend_id=bo.id

WHERE 
		bo.id is NULL;

案例1:哪个部门没有员工

左外

SELECT 
		d.* ,e.employee_id

FROM 
		departments d

LEFT OUTER JOIN 
		employees e

ON 
		d.department_id=e.department_id

WHERE 
		e.employee_id IS NULL;

右外

SELECT 
		d.*,e.employee_id

FROM 
		employees e

RIGHT OUTER JOIN
		departments d

ON 
		d.department_id=e.department_id

WHERE 
		e.employee_id IS NULL;

全外

USE girls;

SELECT
		b.* , bo.*

FROM 
		beauty b

FULL OUTER JOIN 
		boys bo

on 
		b.boyfriend_id-bo.id;

交叉连接

SELECT
		b.*,bo.*

FROM 
		beauty b

CROSS JOIN 
		boys bo;

进阶七:子查询

含义:出现在其他语句中的select语句,称为子查询或者内查询

外部的查询语句,称为主查询或者外查询

分类:

按子查询出现的位置:

SELECT后面:仅仅支持标量子查询

from后面:支持表子查询

where或having后面:标量子查询、列子查询、行子查询

exits后面(相关子查询):表子查询

按结果集的行列数不同:

标量子查询(结果集只有一行一列)

列子查询(结果集只有一列多行)

行子查询(结果集只有一行多列)

表子查询(结果集为多行多列)

where或having后面

1.标量子查询(单行子查询)

2.列子查询(多行子查询)

3.行子查询(多列多行)

特点:

1.子查询放在小括号内,

2.子查询一般放在条件的右侧

3.标量子查询,一般搭配着单行操作符使用

> < >= <= <> =

4.列子查询一般搭配着多行操作符使用

in any/some all

1.标量子查询

案例一:谁的工资比 Abel高?

查询Abel的工资

SELECT
		salary

FROM 
		employees

WHERE 
		last_name ='Abel';

查询员工的信息,满足条件1的结果

SELECT *

FROM 
		employees

WHERE salary > (

			SELECT salary

			FROM employees

			WHERE last_name = 'Abel'    
);
 

案例2:返回job_id与141号员工相同,salary比143号员工多 姓名,job_id和工资

查询141号的job_id

SELECT
		job_id

FROM 
		employees

WHERE 
		employee_id = 141;

143号员工的salary

SELECT
		salary

FROM 
		employees

WHERE 
		employee_id =143;

查询员工的姓名 job_id=1和工资>2

SELECT 
		last_name,job_id,salary

FROM 
		employees

WHERE job_id = (

			SELECT job_id

			FROM employees

			WHERE employee_id = 141

) AND 
		salary >(

			SELECT salary

			FROM employees

			WHERE employee_id =143

);

案例3:返回公司工资最少的员工last_name ,job_id和salary

查询工资最少

SELECT MIN(salary) FROM employees;

查询对应值 salary = 1.

SELECT 
		last_name,job_id,salary

FROM 
		employees

WHERE salary = (

			SELECT MIN(salary)

			FROM employees

);

案例4:查询最低工资 大于50号部门最低工资的部门id和其最低工资

查询50号部门的最低工资

SELECT
		MIN(salary)

FROM 
		employees

WHERE 
		department_id = 50

查询每个部门的最低工资

SELECT
		MIN(salary),department_id

FROM 
		employees

GROUP BY
		department_id;

筛选2满足 min(salary)>1的结果

SELECT 
		MIN(salary),department_id

FROM 
		employees

GROUP BY
		department_id

HAVING MIN(salary)> (

			SELECT MIN(salary)

			FROM employees

			WHERE department_id = 50

);

2.列子查询(多行子查询)

案例1:返回location_id是1400或者是1700的部门中的所有员工姓名

查询location_id是1400或者1700的部门编号

SELECT 
		department_id

FROM 
		departments

WHERE 
		location_id in(1400,1700);

查询员工姓名,要求部门号是1列表中的某一个

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

查询job_id为‘IT_PROG’部门任一工资

SELECT DISTINCT
		salary

FROM 
		employees

WHERE 
		job_id = 'IT_PROG';

查询员工号,姓名,job_id以及salary,salary

SELECT 
		last_name,employee_id,job_id,salary

FROM 
		employees

WHERE salary < any(

			SELECT DISTINCT salary

			FROM employees

			WHERE job_id = 'IT_PROG'

)AND job_id <>'IT_PROG';

另一种写法

SELECT 
		last_name,employee_id,job_id,salary

FROM 
		employees

WHERE salary < (

			SELECT MAX(salary)

			FROM employees

			WHERE job_id = 'IT_PROG'

)AND job_id <>'IT_PROG';

3.行子查询(一行多列,多行多列)

案例:查询员工编号最小并且工资最高的员工编号

查询最小的员工编号

SELECT 
		MIN(employee_id)

FROM 
		employees;

查询出最高的工资

SELECT
		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后面

案例:查询每个部门的员工个数

SELECT d.*,(

	SELECT COUNT(*)

	FROM employees e

	WHERE e.department_id =d.department_id

) 个数

FROM departments d;

放在from后面

案例:查询每个部门的平均工资的工资等级

查询每个部门的平均工资

SELECT 
		AVG(salary) ,department_id

FROM 
		employees

GROUP BY
		department_id;

连接1的结果集和job_grades表,筛选条件平均工资 BETWEEN lowest_sal and highest_sal

SELECT 
		ag_dep.*,g.grade_level

FROM (

SELECT  AVG(salary) ag,department_id

FROM employees

GROUP BY department_id

) ag_dep 

INNER JOIN 
		job_grades g

ON     
		ag_dep.ag BETWEEN lowest_sal AND highest_sal;

进阶八:分页查询

应用场景:当要显示的数据,一页显示不全,需要分页提交sql请求

语法:

SELECT     
		查询列表
FROM 
 		表

【JOIN type join 表2

  ON 连接条件

  WHERE 筛选条件

 GROUP BY 分组字段

 having 分组后筛选

 ORDER BY 排序的字段】

limit offset,size;

#offset表示要显示条目的起始索引(从0开始)

#size表示显示的条目个数

特点:

1.limit语句放在查询语句的最后,并且执行也是最后执行。

2.公式:要显示的页数是page,每页显示的条目数是size

SELECT    
		查询列表

FROM

		limit (page-1)*size ,size;

案例1:查询前五条员工信息

SELECT * FROM employees

LIMIT 0,5;

或者

SELECT * FROM employees

LIMIT 5;

案例2:查询第11-25条的信息

SELECT * FROM employees

LIMIT 10,15;

案例3:有奖金的员工信息,并且工资较高的排名前10的员工信息

SELECT * 
FROM 
		employees    

WHERE 
		commission_pct is NOT NULL

ORDER BY 
		salary DESC

LIMIT 10;

进阶九:联合查询

UNION 联合/合并 :将多条语句的查询结果合并成一个结果。

语法:

查询语句1

union

查询语句2

union

...

应用场景:要查询的结果来自于多个表,且多个表之间没有直接连接关系,但查询的信息一致时。

特点:

​ 1.要求多条查询语句的查询列数是一致的

​ 2.要求多条查询语句的查询的每一列的类型和顺序最好一致!

​ 3.不想去重用 :UNION ALL,默认是去重的

引入的案例:查询部门编号>90或者邮箱包含a的员工信息

以前的方法

SELECT *

FROM
		employees

WHERE 
		email LIKE '%a%'

OR 
		department_id>90;

union方法

SELECT * FROM employees WHERE email like '%a%'

UNION

SELECT * FROM employees WHERE department_id>90;

进阶十:DML语言

数据操纵语言:

数据插入:INSERT

数据修改:UPDATE

数据删除:DELETE

一、插入语句

经典插入

语法:

insert INTO 表名(列名,...) values(值1,...);

INSERT INTO 表名

set 列名=值,列名=值,...

1.插入的值类型要和列的类型兼容或一致

2.不可以为null的列必须插入值,可以为null的列是如何插入值的?

方式一:直接写NULL

方式二:列不写,NULL也不写

3.**列的顺序是否可以颠倒?**yes,可以。

4.列数和值的个数必须一致

5.可以省略列名,默认是所有列,而且列的顺序和表中列的顺序一致

INSERT INTO beauty

VALUES(18,'畅','男',NULL,'1165654',NULL,NULL);

直接插入案例

INSERT INTO beauty

SET id=19,NAME='大哥',phone='456465';

两种方式大PK

方式一有方式二无:支持插入多行(一次性加入多个数据行),支持子查询。

二、修改语句

1.修改单表的记录

语法:

update 
		表名s

set 
		列=新值,列=新值,...

WHERE 
		筛选条件;

2.修改多表的记录【补充】

语法:

sql92语法:

update 
		表1 别名, 表2 别名

SET 
		列=值,...

where 
		连接条件

and 
		筛选条件;

Sql99语法:

update 

		表1 别名

inner|left|right join 
		表2 别名

on 
		连接条件

set 
		列=值,...

where 
		筛选条件;

案例1:修改单表的记录

修改beauty表中姓唐的女神的电话为156456465

UPDATE beauty SET phone = '156456465'

WHERE NAME LIKE '唐%';

案例2:修改boys表中的id号为2的名称为张非,并且魅力值改为10

UPDATE boys SET boyname='张非',usercp='10'

WHERE id ='2';

2.修改多表的记录【补充】

案例1:修改张无忌的女朋友的手机号为“156465465”

UPDATE boys bo

INNER JOIN beauty b ON bo.id = b.boyfriend_id

SET b.phone ='156465465'

WHERE bo.boyName = '张无忌';

案例2:修改没有男朋友的女神的男朋友编号都为2号(张飞)

UPDATE boys bo

RIGHT JOIN beauty b ON bo.id = b.boyfriend_id

SET b.boyfriend_id = '2'

WHERE b.id is NULL;

3.删除语句

方式一:delete

语法:

(一删就是整行,所以需要加筛选条件)

1.单表删除

delete FROM 表名 where 筛选条件

2.多表删除【补充】

方式二:TRUNCATE

语法: TRUNCATE table 表名; (全部删掉)

sql92语法:

delete 表1的别名,表2的别名

from 表1 别名 ,表2 别名

WHERE 连接条件

AND 筛选条件

sql99语法:

DELETE 表1的别名,表2的别名    

FROM 表1 别名

INNER|left|right| join 表2 别名 on 连接条件

where 筛选条件

方式一:delete

单表删除

案例一:删除手机号以9为结尾的女生信息

DELETE FROM beauty WHERE phone LIKE '%9';

多表删除

案例:删除张无忌的女朋友的信息

DELETE b FROM beauty b

INNER JOIN boys bo ON b.boyfriend_id=bo.id

WHERE bo.boyName ='张无忌'

案例:删除黄晓明的信息以及他女朋友的信息

DELETE b,bo

FROM beauty b

JOIN boys bo ON b.boyfriend_id=bo.id

WHERE bo.boyName = '黄晓明'

DELETE pk TRUNCATE**

1.delete可以加where条件,TRUNCATE不可以。

2.TRUNCATE删除效率稍微高点。

3.假如要删除的表中有自增长列,

如果用delete删除后,再插入数据,自增长列的值从断点开始,

而truncate删除后。再插入数据,自增长列的值从1开始。

4.TRUNCATE 删除没有返回值,delete有。

5.TRUNCATE删除后不可以回滚,DELETE可以。

进阶十一:DDL语言

数据定义语言

库和表的管理

一、库的管理:创建、修改、删除

二、表的管理:创建、修改、删除

创建:create

修改:alter

删除:Drop

1.表的创建 ★

create table 表名(

列名 列的类型【(长度) 约束】,

列名 列的类型【(长度) 约束】,

列名 列的类型【(长度) 约束】,

...

列名 列的类型【(长度) 约束】

)

案例:创建表book

CREATE TABLE if NOT EXISTS book(

				id INT,#书的编号

				bName VARCHAR(20),#图书名

				price DOUBLE,#价格

 				authorId INT, #图书作者    

				publishDate DATETIME#出版日期


);

创建作者表author

CREATE TABLE author(
			 Id INT,

 			au_name VARCHAR(20),

 			nation VARCHAR(20)

);

2.表的修改

修改列名、修改列的类型或者约束

添加新列、删除列、修改表名

修改列名

ALTER TABLE book CHANGE COLUMN publishdate pubDate DATETIME;

修改列的类型

ALTER TABLE book MODIFY COLUMN pubdate TIMESTAMP;

添加新列

ALTER TABLE author ADD COLUMN annual DOUBLE;

删除列

ALTER TABLE author DROP COLUMN annual;

修改表名

ALTER TABLE author RENAME TO book_author;

3.表的删除

DROP TABLE IF EXISTS book_author;

通用的写法:

DROP DATABASE is EXISTS 旧的库名

CREATE DATABASE 新库名;

 

DROP TABLE IS EXISTS 旧表名;

CREATE TABLE 新表名();

**4.**表的复制

INSERT INTO author VALUES(1,'村上春树','日本'),

(2,'莫言','中国'),

(3,'冯唐','中国'),

(4,'金庸','中国'); 

1.仅仅复制表的结构

CREATE TABLE copy LIKE author;

2.复制表的结构+数据

CREATE TABLE copy2

SELECT * FROM author;

3.只复制一部分

CREATE TABLE copy3

SELECT id,au_name

FROM author 

WHERE nation='中国';

复制一部分,没内容

CREATE TABLE copy4

SELECT id,au_name

FROM author

WHERE 1=2;

进阶十二:常见的数据类型

数值型:

​ 整型

​ 小数:定点数,浮点数

字符型:

​ 较短的文本:char,varchar

​ 较长的文本:text,blob(较长的二进制数字)

日期型

1.整型

分类:TINYINT 1, SMALLINT 2, MEDIUMINT 3, int/INTEGER 4, BIGINT 8 (个子节)

特点:

1.如果不设置有无符号,默认是有符号,想设置无符号需要设置UNSIGNED

2.如果插入的数值超过了整型的范围,会报异常,并且插入的是临界值

3.如果不设置长度,会有默认的长度。

4.长度代表了显示的最大宽度,如果不够会用0在左边填充,但是必须搭配zerofill使用

如何设置无符号和有符号

CREATE TABLE tab_int(

t1 INT,

t2 INT UNSIGNED

);

INSERT INTO tab_int VALUES (-123456,12456);

2.小数

浮点型:float(M,D) double(M,D)

定点型:dec(M,D) DECIMAL(M,D)

特点:1.关于M和D的意思—M:整数部位+小数部位 D:小数部位 如果超过范围,则插入临界值。

​ 2.M和D都可以省略,如果是decimal,则M默认是10,D默认是0,

​ 如果插入的是float或double,则会随着插入的数值的精度来决定精度。

对比:定点型的精度较高,如果要求插入的数值的精度较高,则优先使用它(货币运算等)。

举例子

CREATE TABLE tab_float(

			f1 FLOAT(5,2),

			f2 DOUBLE(5,2),

			f3 DECIMAL(5,2)

);

SELECT  * FROM tab_float;

INSERT INTO tab_float VALUES(123.45,123.45,123.45);

INSERT INTO tab_float VALUES(123.456,123.456,123.456);

INSERT INTO tab_float VALUES(123.4,123.4,123.4);

INSERT INTO tab_float VALUES(1523.4,1523.4,1523.45);

#原则:所选择的类型越简单越好

3.字符型

较短的文本:

char

VARCHAR

其他:

VARBINARY和binary适用于保存较短的二进制

enum用于保存枚举,set用于保存集合

较长的文本:

text

blob(较大的二进制)

比较:

写法 M的意思 特点 空间耗费 效率
char char(M) 最大字符数 固定长度的字符 比较耗费
VARCHAR VARCHAR(M) 最大的字符数 可变长度的字符 比较节省

4.日期型

分类:

date只保存日期

time只保存时间

year只保存年

datetime保存日期+时间

TIMESTAMP保存日期+时间

比较:

字节 范围 时区等的影响
datetime 8 较大1000-9999年 不受
TIMESTAMP 4 较小1970-2038年

进阶十三:常见约束

一种限制,用于限制表中的数据,为了保证表中的数据的准确和可靠性

分类:

NOT NULL :非空,用于保证该字段的值不能为空

比如姓名、学号等

DEFAULT:默认,用于保证该字段的值有默认值

比如性别

PRIMARY KEY :主键,用于保证该字段的值有唯一值,并且非空

比如学号、员工编号等

UNIQUE : 唯一,用于保证该字段的值有唯一值,可以为空

比如座位号

CHECK:检查约束【MySQL中不支持】[兼容性…不报错,但是没效果]

比如:年龄和性别

FOREIGN KEY :外键,用于限制两个表的关系,用于保证该字段的值必须来自于主表的关联列的值

比如:学生表的专业编号,员工表的部门编号,员工表的工种编号

1.添加约束的时机

1.创建表时

2.修改表时

2.约束的添加分类

1.列级约束

六大约束语法上都支持,但外键约束没有效果。

2.表级约束

除了非空,默认,其他的都支持。

CREATE TABLE 表名(

		字段名 字段类型 列级约束

		字段名 字段类型 

		表级约束
);

创建表时添加约束

#1.添加列级约束

语法:

​ 直接在字段名和类型后面追加约束类型即可


CREATE table stuinfo(

			id INT PRIMARY KEY,#主键

			stuName VARCHAR(20) NOT NULL ,#非空

			gender CHAR(1) CHECK(gender='男'OR gender='女'),#检查性别

			seat INT UNIQUE ,#唯一

 			age INT DEFAULT 18    #默认约束

);
CREATE TABLE major(

    	id INT PRIMARY key,

		majorName VARCHAR(20)

);

添加表级约束

在各个字段最下面

【CONSTRAINT 约束名】(可以去掉) 约束类型(字段名)

#通用写法:

CREATE table IF NOT EXISTS stuinfo(

			id INT PRIMARY KEY,

			stuname VARCHAR(20) NOT NULL,

		    gender CHAR(1),

 			age INT DEFAULT 18,

 			seat INT UNIQUE ,

	   		majorid INT,

			FOREIGN KEY(majorid) REFERENCES major(id)

);

主键和唯一的区别

1.均可以保证唯一性

2.主键不允许为空,唯一可以为空

3.主键最多为一个(0/1)

唯一可以有多个

4.都允许组合,但是不推荐

外键的特点

1.要求在从表设置外键关系

2.从表的外键列的类型和主表中的关联列的类型要求一致或者兼容,名称无要求

3.主表的关联列必须是个key(一般是主键或者唯一)

4.插入数据时,必须先插入主表(科目),再插入从表(学生),

删除数据时,先删除从表,再删除主表。

3.标识列

又称为自增序列

含义:可以不用手动的插入值,系统提供默认的序列值

特点:1.标识列和key搭配

​ 2.一个表中可以有至多一个标识列

​ 3.标识列类型只能是数值型

​ 4.标识列可以通过 SET auto_increment_increment=3;设置步长,可以通过手动插入值,设置起始值。

创建表时设置标识列

DROP TABLE IF EXISTS tab_identity;

CREATE TABLE tab_identity(

			id INT PRIMARY KEY auto_increment,

			NAME VARCHAR(20) 

);

修改表时设置标识列

ALTER TABLE tab_identity MODIFY COLUMN id INT PRIMARY KEY auto_increment;

修改表时删除标识列

ALTER TABLE tab_identity MODIFY COLUMN id INT PRIMARY KEY;

进阶十四:TCL语言 事务控制语言

事务:一个或一组sql语句组成一个执行单元,这个执行单元要么全部执行,要么全部不执行。

案例:转账

张三丰 1000

郭襄 1000

张三丰转给郭襄500

张三丰 500

郭襄 1500

事务(ACID)的属性:

1.原子性:原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生要么都不发生。

2.一致性:事务必须使数据库从一个一致性状态变成另外一个一致性状态。

3.隔离性:事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务

是隔离的,并发执行的各个事务之间是不能互相干扰的。

4.持久性:持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,

接下来的其他操作和数据库故障不应该对其有任何影响。

事务的创建:

隐式事务:事务没有明显的开启和结束标记 比如:INSERT UPDATE DELETE 语句

显式事务:事务具有明显的开启和结束的标记(前提,必须先设置自动提交功能为禁用)

1.开启事务

SET autocommit=0;(关闭自动提交)

2.编写事务中的sql语句(SELECT INSERT UPDATE SELECT)

语句1;

语句2;

3.结束事务

COMMIT; 提交事务

ROLLBACK; 回滚事务

NOT NULL :非空,用于保证该字段的值不能为空

比如姓名、学号等

DEFAULT:默认,用于保证该字段的值有默认值

比如性别

PRIMARY KEY :主键,用于保证该字段的值有唯一值,并且非空

比如学号、员工编号等

UNIQUE : 唯一,用于保证该字段的值有唯一值,可以为空

比如座位号

CHECK:检查约束【MySQL中不支持】[兼容性…不报错,但是没效果]

比如:年龄和性别

FOREIGN KEY :外键,用于限制两个表的关系,用于保证该字段的值必须来自于主表的关联列的值

比如:学生表的专业编号,员工表的部门编号,员工表的工种编号

1.添加约束的时机

1.创建表时

2.修改表时

2.约束的添加分类

1.列级约束

六大约束语法上都支持,但外键约束没有效果。

2.表级约束

除了非空,默认,其他的都支持。

CREATE TABLE 表名(

		字段名 字段类型 列级约束

		字段名 字段类型 

		表级约束
);

创建表时添加约束

#1.添加列级约束

语法:

​ 直接在字段名和类型后面追加约束类型即可


CREATE table stuinfo(

			id INT PRIMARY KEY,#主键

			stuName VARCHAR(20) NOT NULL ,#非空

			gender CHAR(1) CHECK(gender='男'OR gender='女'),#检查性别

			seat INT UNIQUE ,#唯一

 			age INT DEFAULT 18    #默认约束

);
CREATE TABLE major(

    	id INT PRIMARY key,

		majorName VARCHAR(20)

);

添加表级约束

在各个字段最下面

【CONSTRAINT 约束名】(可以去掉) 约束类型(字段名)

#通用写法:

CREATE table IF NOT EXISTS stuinfo(

			id INT PRIMARY KEY,

			stuname VARCHAR(20) NOT NULL,

		    gender CHAR(1),

 			age INT DEFAULT 18,

 			seat INT UNIQUE ,

	   		majorid INT,

			FOREIGN KEY(majorid) REFERENCES major(id)

);

主键和唯一的区别

1.均可以保证唯一性

2.主键不允许为空,唯一可以为空

3.主键最多为一个(0/1)

唯一可以有多个

4.都允许组合,但是不推荐

外键的特点

1.要求在从表设置外键关系

2.从表的外键列的类型和主表中的关联列的类型要求一致或者兼容,名称无要求

3.主表的关联列必须是个key(一般是主键或者唯一)

4.插入数据时,必须先插入主表(科目),再插入从表(学生),

删除数据时,先删除从表,再删除主表。

3.标识列

又称为自增序列

含义:可以不用手动的插入值,系统提供默认的序列值

特点:1.标识列和key搭配

​ 2.一个表中可以有至多一个标识列

​ 3.标识列类型只能是数值型

​ 4.标识列可以通过 SET auto_increment_increment=3;设置步长,可以通过手动插入值,设置起始值。

创建表时设置标识列

DROP TABLE IF EXISTS tab_identity;

CREATE TABLE tab_identity(

			id INT PRIMARY KEY auto_increment,

			NAME VARCHAR(20) 

);

修改表时设置标识列

ALTER TABLE tab_identity MODIFY COLUMN id INT PRIMARY KEY auto_increment;

修改表时删除标识列

ALTER TABLE tab_identity MODIFY COLUMN id INT PRIMARY KEY;

进阶十四:TCL语言 事务控制语言

事务:一个或一组sql语句组成一个执行单元,这个执行单元要么全部执行,要么全部不执行。

案例:转账

张三丰 1000

郭襄 1000

张三丰转给郭襄500

张三丰 500

郭襄 1500

事务(ACID)的属性:

1.原子性:原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生要么都不发生。

2.一致性:事务必须使数据库从一个一致性状态变成另外一个一致性状态。

3.隔离性:事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务

是隔离的,并发执行的各个事务之间是不能互相干扰的。

4.持久性:持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,

接下来的其他操作和数据库故障不应该对其有任何影响。

事务的创建:

隐式事务:事务没有明显的开启和结束标记 比如:INSERT UPDATE DELETE 语句

显式事务:事务具有明显的开启和结束的标记(前提,必须先设置自动提交功能为禁用)

1.开启事务

SET autocommit=0;(关闭自动提交)

2.编写事务中的sql语句(SELECT INSERT UPDATE SELECT)

语句1;

语句2;

3.结束事务

COMMIT; 提交事务

ROLLBACK; 回滚事务

SAVEPOINT 节点名;设置节点(保存点)类似于断点

B站MySQL(尚硅谷)学习笔记_第2张图片

DELETE 和 TRUNCATE在事务使用时的区别:

演示delete:支持回滚

SET autocommit = 0;
START TRANSACTION;
DELETE FROM account;
ROLLBACK;

演示truncate:不支持回滚

SET autocommit=0;
START TRANSACTION;
TRUNCATE TABLE account;
ROLLBACK;

演示savepoint的使用

#SAVEPOINT只搭配rollback使用
SET autocommit=0;
START TRANSACTION;
DELETE FROM account WHERE id=25;
SAVEPOINT a;#设置保存点
DELETE FROM account WHERE id=28;
ROLLBACK TO a;#回滚到保存点处
#最终效果只有id25删掉了28没有删掉	

进阶十五:视图

MySQL从5.0.1版本开始提供视图功能。一种虚拟存在的表,行和列的数据来自定义视图的查询中使用的表,并且

是在使用视图时动态生成的,只保存了sql逻辑,并不保存查询结果

应用场景:

1.多个地方用到同样的查询结果

2.该查询结果使用sql语句较复杂

案例:查询姓张的学生名和专业名

普通解法

SELECT 
		stuname,majorname

FROM 
		stuinfo s

INNER JOIN major m on s.majorid=m.id

WHERE 
		s.stuname like '张%';

利用视图

CREATE VIEW v1

AS

SELECT 
		stunname,majorname

FROM 
		stuinfo s

INNER JOIN major m on s.majorid=m.id;

SELECT * FROM v1

WHERE 	
		s.stuname like '张%';

#注意:为什么使用*,因为视图中就只有一开始指定好的信息

1.如何创建视图?

语法:

SELECT VIEW 视图名

AS

查询语句;

案例1:查询邮箱中包含a字符的员工名、部门名和工种信息

#1.创建

CREATE VIEW myv1

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;

#2.使用

SELECT * FROM myv1 WHERE  last_name like '%a%';

案例2:查询各部门的平均工资级别

#创建视图查看每个部门的平均工资

CREATE VIEW myv2

AS

SELECT AVG(salary) ag,department_id

FROM employees

GROUP BY department_id;

#使用

SELECT myv2.ag,g.grade_level

FROM myv2

JOIN job_grades g

ON myv2.ag BETWEEN g.lowest_sal AND g.highest_sal;

 

案例3:查询平均工资最低的部门信息

SELECT * FROM myv2

ORDER BY ag 

LIMIT 1;

案例4:查询平均工资最低的部门名和工资

CREATE VIEW myv3

AS 

SELECT * FROM myv2 ORDER BY ag LIMIT 1;

 

SELECT d.*,m.ag 

FROM myv3 m

JOIN departments d

on m.department_id = d.department_id;

2.视图的修改

#方式一:

CREATE or REPLACE view 视图名

as

查询语句;


#例:

CREATE OR REPLACE VIEW myv3

AS 

SELECT AVG(salary),job_id

FROM employees

GROUP BY job_id;
#方式二:

#语法:

ALTER view 视图名

AS

查询语句;    

#例:

ALTER view myv3

AS

SELECT * FROM employees;

3.删除视图

语法:drop VIEW 视图名,视图名,...;

例:

DROP view myv1,myv2;

4.查看视图

SHOW CREATE view myv3;

5.视图的更新

B站MySQL(尚硅谷)学习笔记_第3张图片

CREATE OR REPLACE VIEW myv1

AS 

SELECT last_name,email

FROM employees;
#1.插入

INSERT INTO myv1 VALUES('张飞','[email protected]');

#注意:这里的修改视图会影响到原来的表的内容

#2.修改

UPDATE myv1 SET last_name ='张无忌' WHERE last_name='张飞';

#3.删除

DELETE FROM myv1 WHERE last_name ='张无忌';
视图和表的对比 是否占用物理空间 使用
视图:CREATE view 没有(仅仅保存了逻辑,没有保留数据) 增删改查,一般不能增删改
表:CREATE TABLE 占用 占用 增删改查

进阶十六:变量

系统变量:

​ 全局变量

​ 会话变量

自定义变量:

​ 用户变量

​ 局部变量

1、系统变量

说明:变量由系统提供,不是用户定义,属于服务器层面。

使用的语法:

1.查看所有的系统变量

SHOW GLOBAL |【session】 VARIABLES;

2.查看满足条件的部分系统变量

SHOW GLOBAL|【SESSION】 VARIABLES like '%char%';

3.查看指定的某个系统变量的值

SELECT @@global|【SESSION】.系统变量名

4.为某个系统变量赋值

方式一

set GLOBAL |【session】 系统变量名 = 值;

方式二

set @@GLOBAL |【session】.系统变量名 =值;

注意:如果是全局级别,用GLOBAL

如果是会话级别,则需要加session,如果不写,则默认是session

全局变量:

作用域:服务器每次启动将为所有的全局变量赋初始值,针对于所有的会话(连接)有效,但不能跨重启。

1.查看所有的全局变量

SHOW GLOBAL VARIABLES;

2.查看部分的全局变量

SHOW GLOBAL VARIABLES LIKE '%CHAR%';

3.查看指定的全局变量的值

SELECT @@global.autocommit;

SELECT @@tx_isolation;

4.为某个指定的全局变量赋值

SET @@global.autocommit=0;

会话变量:

作用域:仅仅针对于当前会话(连接)有效。

1.查看所有的会话变量

SHOW VARIABLES;

2.查看部分的会话变量

SHOW VARIABLES LIKE '%CHAR%';

SHOW SESSION VARIABLES LIKE '%CHAR%';

3.查看指定的会话变量的值

SELECT @@session.tx_isolation;

SELECT @@tx_isolation;

4.为某个指定的会话变量赋值

SET @@session.tx_isolation='read-UNCOMMITTED';

SET SESSION tx_isolation = 'read-COMMITTED';

2、自定义变量

说明:变量是用户自定义的,不是由系统的。

使用步骤:声明、赋值、使用(查看、比较、运算等)

用户变量

作用域:针对于当前会话(连接)有效,和会话变量的作用域一致应用在任何地方,也就是begin end里面或者begin end外面

赋值的操作符 : =或:=

1.声明并初始化

SET @用户变量名 =值;

SET @用户变量名:=值;

SELECT @用户变量名:=值;

2.赋值(更新用户变量的值)

方式一:通过set或者select

SET @用户变量名 =值;

SET @用户变量名:=值;

SELECT @用户变量名:=值;

例:

SET @name = 'john';

SET @name=100;

方式二:通过select INTO

SELECT 字段名 INTO 变量名

FROM 表;

例:

SET @count =1

SELECT COUNT(*) INTO @count

FROM employees;

3.(使用)查看用户变量的值

SELECT @用户变量名;

SELECT @count;

局部变量

作用域 :仅仅在定义他的begin END中有效,应用在begin end中的第一句话。

1.声明

DECLARE 变量名 类型;

DECLARE 变量名 类型 DEFAULT 值;

2.赋值

方式一:通过set 或select

set 局部变量名=值;

set 局部变量名:=值;

SELECT @局部变量名:=值;

方式二:通过select INTO

SELECT 字段 into 局部变量名

FROM 表;

3.使用

SELECT 局部变量名;

对比用户变量和局部变量

作用域 定义和使用的位置 语法
用户变量 当前会话 会话中的任何地方 必须加@符号,不用限定类型
局部变量 begin END中 只能在begin end中,且为第一句话 一般不用加@符号,需要限定类型

案例:声明两个变量并赋初始值,求和并打印

1.用户变量

SET @m=1;

SET @n=2;

SET @sum=@m+@n;

SELECT @sum;

2.局部变量

DECLARE m INT DEFAULT 1;

DECLARE n INT DEFAULT 2;

DELETE sum INT;

SET sum=m+n;

SELECT sum;

进阶十七:存储过程和函数

类似于Java中的方法,好处

1.提高代码的重用性

2.简化操作

存储过程

含义:一组预先编译好的SQL语句的集合,理解成批处理语句

1.提高代码的重用性

2.简化操作

3.减少了编译次数并且减少了和数据库服务的连接次数,提高了效率。

1:创建语法

CREATE PROCEDURE 存储过程名(参数列表)

BEGIN

存储过程体(一组合法的SQL语句)

END

注意:

1.参数列表包含三个部分:

参数模式 参数名 参数类型

举例:

IN stuname VARCHAR(20);

参数模式:

in :该参数可以作为输入:也就是该参数需要调用方传入值

OUT:该参数可以作为输出,也就是该参数可以作为返回值

inout:该参数既可以作为输入也可以作为输出,也就是该参数既需要传入值又可以返回值。

2.如果存储过程体仅仅只有一句话,begin END 可以省略

存储过程体中的每条SQL语句的结尾要求必须加分号。

存储过程的结尾可以使用 delimiter重新设置 语法:delimiter 结束标记

2:调用语法

CALL 存储过程名(实参列表);

1.空参的存储过程

SELECT * FROM  admin;

delimiter $

CREATE PROCEDURE myp1()

BEGIN

INSERT INTO admin(username,`password`) 

VALUES('john1','156456'),('lily','0000'),('jvaad','56465'),('dasd','465465'),('4dasd','41324');

END $

2.创建带in模式参数的存储过程

案例1:创建存储过程实现 根据女神名查询对应的男神信息

delimiter $

CREATE     PROCEDURE myp2(IN beautyName VARCHAR(20))

BEGIN

SELECT bo.*

FROM boys bo

RIGHT JOIN beauty b ON bo.id = b.boyfriend_id

WHERE b.name = beautyName;

END $

#调用

delimiter $

CALL myp2('柳岩')$

 

案例2:创建存储过程实现,用户是否登录成功

delimiter $

CREATE PROCEDURE myp3(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(rusult>0,'成功','失败');#使用

end $

3.带out模式的存储过程

案例1:根据女神名,返回对应的男神名

delimiter $

USE girls

CREATE PROCEDURE myp4(in beautyName VARCHAR(20),OUT boyName VARCHAR(20))

BEGIN

SELECT bo.boyName

FROM boys bo

INNER JOIN beauty b ON bo.id=b.boyfriend_id

WHERE b.name=beautyName;

END $

#调用:

delimiter $

CALL myp4('王语嫣',@bname)$

SELECT @bname$

案例2:根据女神名,返回对应的男神名和男神魅力值

delimiter $

CREATE PROCEDURE myp5(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 myp5('王语嫣',@bname,@usercp);

SELECT @bname,@usercp$

4.带inout模式的存储过程

案例1:传入a和b两个值,最终要求a和b都翻倍并返回

delimiter $

CREATE PROCEDURE myp3(INOUT a INT,INOUT b INT)

BEGIN 

		SET a = a*2;

		SET b = b*2;

END $
#调用
delimiter $

SET @m=10$

SET @n=20$

CALL myp3(@m,@n)$

SELECT @m,@n$

题目1:创建存储过程实现传入用户名和密码,插入到admin表中

delimiter $

CREATE PROCEDURE test1 (IN username VARCHAR(20),IN loginPwd VARCHAR(20))

BEGIN

        INSERT INTO admin(admin.username,PASSWORD)

VALUES(username,loginPwd);

END$

题目2:创建存储过程实现传入女神编号,返回女神名称和电话

delimiter $

CREATE PROCEDURE test2(IN id INT,OUT name VARCHAR(20),OUT phone VARCHAR(20))

BEGIN

      SELECT b.name ,b.phone INTO NAME ,phone

 FROM beauty b

 WHERE b.id=id;

END $

题目3:创建存储过程或函数实现传入两个女神生日,返回大小

delimiter $

CREATE PROCEDURE test3(IN birth1 datetime,IN birth2 datetime,out result INT)

BEGIN

SELECT DATEDIFF(birth1,birth2) INTO result;

END $

3.删除存储过程

语法:drop procedure 存储过程名

DROP PROCEDURE p1;

DROP PROCEDURE p2,p3;#不可以! 只可以放一个

4.查看存储过程的信息

SHOW CREATE PROCEDURE myp2;

函数

含义:一组预先编译好的SQL语言的集合,理解成批处理语句

优点:

1.提高了代码的重用性

2.简化操作

3.减少了编译次数并且减少了和数据库服务器的连接次数,提高了效率

区别:

存储过程:可以有零个返回,也可以有多个返回。

函数:必须有且仅有一个返回,零个多个均不行。

1.函数创建语法

CREATE FUNCTION 函数名(参数列表) RETURNS 返回类型

BEGIN

		函数体

END

1.参数列表包含两部分:参数名 参数类型

2.函数体:肯定会有return语句,如果没有会报错。如果return语句没有放在函数体的最后也不会报错,但是不建议。

3.函数体中仅有一句话,则可以省略begin end

4.使用delimiter语句设置结束标记

2.调用语句

SELECT 函数名(参数列表)

案例演示:

1.无参有返回

案例:返回公司的员工个数

SET GLOBAL  = TRUE;

delimiter $

USE myemployees;

CREATE FUNCTION myf1() RETURNS INT

BEGIN

DECLARE c INT DEFAULT 0;

     SELECT count(*) INTO c

FROM employees;

RETURN c;

END $

SELECT myf1()$

2.有参有返回值

案例1:根据员工名,返回他的工资

CREATE FUNCTION myf2(empName VARCHAR(20)) RETURNS DOUBLE

BEGIN 
		
 		 SET @sal=0;#定义用户变量

		 SELECT salary INTO @sal #赋值

 		 FROM employees

 		 WHERE last_name = empName;

		 RETURN @sal;

END $

SELECT myf2('k_ing')$

案例2:根据部门名,返回该部门的平均工资。

CREATE FUNCTION myf3(deptName VARCHAR(20)) RETURNS DOUBLE

BEGIN

		DECLARE sal DOUBLE;

		SELECT AVG(salary) INTO sal

		FROM employees e

		JOIN departments d ON e.department_id=d.department_id

		WHERE d.department_name = deptName;

		RETURN sal;

END$    

SELECT myf3('IT')$ 
3.函数的查看

SHOW CREATE FUNCTION myf3;

4.函数的删除

DROP FUNCTION myf3;

案例:创建函数,实现传入两个float,返回二者之和

delimiter $

CREATE FUNCTION test4(num1 FLOAT ,num2 FLOAT) RETURNS FLOAT

BEGIN

		DECLARE sum FLOAT DEFAULT 0;

		SET sum=num1+num2;

		RETURN sum;

end$

SELECT test4(1,2)$

进阶十八:流程控制结构

  1. 顺序结构:程序从上往下依次执行
  2. 分支结构:程序从两条或多条路径中选择一条去执行
  3. 循环结构:程序在满足一定条件的基础上,重复执行一段代码

1.分支结构

IF函数

功能:实现简单的双分支

语法:

IF(表达式1,表达式2,表达式3)

执行顺序:

如果表达式1成立,则返回2值,否则返回3值。

应用:任何地方

case结构

情况1:类似于Java中的switch语句,一般用于实现的等值判断

语法:

CASE 变量|表达式|字段

		WHEN 要判断的值 THEN 返回的值1或语句n1;

		WHEN 要判断的值 THEN 返回的值2或语句n2;

		...

		ELSE 要返回的值或者语句n;

end CASE;

情况2:类似于Java中的多重if语句,一般用于实现区间判断

CASE 

		WHEN 要判断的条件1 THEN 返回的值1或语句n1;

		WHEN 要判断的条件2 THEN 返回的值2或语句n2;

		...

		ELSE 要返回的值或语句n

end CASE;

特点:

1.可以作为表达式,嵌套在其他语句中使用,可以放在任何地方, BEGIN END 中或begin END 的外面

可以作为独立的语句去使用,只能放在begin end中

2.如果when中的值满足或条件成立,则执行对应的then语句并且结束case,都不满足则执行else中的语句或值

3.else可以省略,如果else省略,并且所有的when条件都不满足,则返回null

if结构

功能:实现多重分支

语法:

if 条件1 then 语句1;

ELSEIF 条件2 then 语句2;

...

【else 语句n;】

END IF;

应用在begin end中

2.循环结构:

分类:while loop repeat

循环控制

ITERATE 类似于continue ,继续

leave类似于break

while

语法:

【标签:】while循环条件 do

循环体;

end WHILE 【标签】;

LOOP

语法:

【标签:】LOOP    

循环体;

end LOOP 【标签】;

#可以用来模拟简单的死循环

REPEAT

语法:

【标签:】repeat

	   循环体;

UNTIL 结束循环的条件

end REPEAT 【标签】;

案例: 批量插入,根据次数插入到admin表中多条记录(没有添加循环控制语句)

delimiter $

DROP PROCEDURE pro_while1$

delimiter $

CREATE PROCEDURE pro_while1(IN insertCount INT)

BEGIN 

  DECLARE i INT DEFAULT 1;

WHILE i<=insertCount DO

    INSERT INTO admin(username,PASSWORD) VALUES(CONCAT('rose',i),'666');

    SET i=i+1;

END WHILE;            

END $

delimiter $

CALL pro_while1(100)$

SELECT * FROM admin$

添加leave语句

案例:批量插入,根据次数插入到admin表中多条记录,如果次数>20则停止

TRUNCATE TABLE admin$

DROP PROCEDURE test_while1$

delimiter $

CREATE PROCEDURE test_while1(IN insertCount INT)

BEGIN

		DECLARE i INT DEFAULT 1;

		a:WHILE i<=insertCount DO

		INSERT INTO admin(username,PASSWORD) VALUES(CONCAT('re',i),'666');

		IF i>=20 THEN LEAVE a;

END IF;

SET i=i+1;

END WHILE a;

END$

delimiter $

CALL test_while1(50)$

SELECT * FROM admin$

笔记到这里就结束了,希望您能通过本文的阅读,掌握数据库的基础知识。

4.查看存储过程的信息

SHOW CREATE PROCEDURE myp2;

函数

含义:一组预先编译好的SQL语言的集合,理解成批处理语句

优点:

1.提高了代码的重用性

2.简化操作

3.减少了编译次数并且减少了和数据库服务器的连接次数,提高了效率

区别:

存储过程:可以有零个返回,也可以有多个返回。

函数:必须有且仅有一个返回,零个多个均不行。

1.函数创建语法

CREATE FUNCTION 函数名(参数列表) RETURNS 返回类型

BEGIN

		函数体

END

1.参数列表包含两部分:参数名 参数类型

2.函数体:肯定会有return语句,如果没有会报错。如果return语句没有放在函数体的最后也不会报错,但是不建议。

3.函数体中仅有一句话,则可以省略begin end

4.使用delimiter语句设置结束标记

2.调用语句

SELECT 函数名(参数列表)

案例演示:

1.无参有返回

案例:返回公司的员工个数

SET GLOBAL  = TRUE;

delimiter $

USE myemployees;

CREATE FUNCTION myf1() RETURNS INT

BEGIN

DECLARE c INT DEFAULT 0;

     SELECT count(*) INTO c

FROM employees;

RETURN c;

END $

SELECT myf1()$

2.有参有返回值

案例1:根据员工名,返回他的工资

CREATE FUNCTION myf2(empName VARCHAR(20)) RETURNS DOUBLE

BEGIN 
		
 		 SET @sal=0;#定义用户变量

		 SELECT salary INTO @sal #赋值

 		 FROM employees

 		 WHERE last_name = empName;

		 RETURN @sal;

END $

SELECT myf2('k_ing')$

案例2:根据部门名,返回该部门的平均工资。

CREATE FUNCTION myf3(deptName VARCHAR(20)) RETURNS DOUBLE

BEGIN

		DECLARE sal DOUBLE;

		SELECT AVG(salary) INTO sal

		FROM employees e

		JOIN departments d ON e.department_id=d.department_id

		WHERE d.department_name = deptName;

		RETURN sal;

END$    

SELECT myf3('IT')$ 
3.函数的查看

SHOW CREATE FUNCTION myf3;

4.函数的删除

DROP FUNCTION myf3;

案例:创建函数,实现传入两个float,返回二者之和

delimiter $

CREATE FUNCTION test4(num1 FLOAT ,num2 FLOAT) RETURNS FLOAT

BEGIN

		DECLARE sum FLOAT DEFAULT 0;

		SET sum=num1+num2;

		RETURN sum;

end$

SELECT test4(1,2)$

进阶十八:流程控制结构

  1. 顺序结构:程序从上往下依次执行
  2. 分支结构:程序从两条或多条路径中选择一条去执行
  3. 循环结构:程序在满足一定条件的基础上,重复执行一段代码

1.分支结构

IF函数

功能:实现简单的双分支

语法:

IF(表达式1,表达式2,表达式3)

执行顺序:

如果表达式1成立,则返回2值,否则返回3值。

应用:任何地方

case结构

情况1:类似于Java中的switch语句,一般用于实现的等值判断

语法:

CASE 变量|表达式|字段

		WHEN 要判断的值 THEN 返回的值1或语句n1;

		WHEN 要判断的值 THEN 返回的值2或语句n2;

		...

		ELSE 要返回的值或者语句n;

end CASE;

情况2:类似于Java中的多重if语句,一般用于实现区间判断

CASE 

		WHEN 要判断的条件1 THEN 返回的值1或语句n1;

		WHEN 要判断的条件2 THEN 返回的值2或语句n2;

		...

		ELSE 要返回的值或语句n

end CASE;

特点:

1.可以作为表达式,嵌套在其他语句中使用,可以放在任何地方, BEGIN END 中或begin END 的外面

可以作为独立的语句去使用,只能放在begin end中

2.如果when中的值满足或条件成立,则执行对应的then语句并且结束case,都不满足则执行else中的语句或值

3.else可以省略,如果else省略,并且所有的when条件都不满足,则返回null

if结构

功能:实现多重分支

语法:

if 条件1 then 语句1;

ELSEIF 条件2 then 语句2;

...

【else 语句n;】

END IF;

应用在begin end中

2.循环结构:

分类:while loop repeat

循环控制

ITERATE 类似于continue ,继续

leave类似于break

while

语法:

【标签:】while循环条件 do

循环体;

end WHILE 【标签】;

LOOP

语法:

【标签:】LOOP    

循环体;

end LOOP 【标签】;

#可以用来模拟简单的死循环

REPEAT

语法:

【标签:】repeat

	   循环体;

UNTIL 结束循环的条件

end REPEAT 【标签】;

案例: 批量插入,根据次数插入到admin表中多条记录(没有添加循环控制语句)

delimiter $

DROP PROCEDURE pro_while1$

delimiter $

CREATE PROCEDURE pro_while1(IN insertCount INT)

BEGIN 

  DECLARE i INT DEFAULT 1;

WHILE i<=insertCount DO

    INSERT INTO admin(username,PASSWORD) VALUES(CONCAT('rose',i),'666');

    SET i=i+1;

END WHILE;            

END $

delimiter $

CALL pro_while1(100)$

SELECT * FROM admin$

添加leave语句

案例:批量插入,根据次数插入到admin表中多条记录,如果次数>20则停止

TRUNCATE TABLE admin$

DROP PROCEDURE test_while1$

delimiter $

CREATE PROCEDURE test_while1(IN insertCount INT)

BEGIN

		DECLARE i INT DEFAULT 1;

		a:WHILE i<=insertCount DO

		INSERT INTO admin(username,PASSWORD) VALUES(CONCAT('re',i),'666');

		IF i>=20 THEN LEAVE a;

END IF;

SET i=i+1;

END WHILE a;

END$

delimiter $

CALL test_while1(50)$

SELECT * FROM admin$

笔记到这里就结束了,希望您能通过本文的阅读,掌握数据库的基础知识。

笔者后面有时间也会将MySQL高级进阶笔记发出来,仅供大家学习。如果您觉得本文还不错,三连+关注一下我吧,我也会持续更新出高质量的文章。

你可能感兴趣的:(笔记,mysql,数据库)