Mysql基础--详细解读

Mysql

一、数据库简介

1、数据库的好处

1.持久化数据到本地
2.可以实现结构化查询,方便管理

2、数据库相关概念

1、DB:数据库,保存一组有组织的数据的容器
2、DBMS:数据库管理系统,又称为数据库软件(产品),用于管理DB中的数据
3、SQL:结构化查询语言,用于和DBMS通信的语言

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

1、将数据放到表中,表再放到库中
2、一个数据库中可以有多个表,每个表都有一个的名字,用来标识自己。表名具有唯一性。
3、表具有一些特性,这些特性定义了数据在表中如何存储,类似java中 “类”的设计。
4、表由列组成,我们也称为字段。所有表都是由一个或多个列组成的,每一列类似java 中的”属性”
5、表中的数据是按行存储的,每一行类似于java中的“对象”。

二、数据库的基础操作

1、MySQL服务的启动和停止

方式一:计算机——右击管理——服务
方式二:通过管理员身份运行
net start 服务名(启动服务)
net stop 服务名(停止服务)

2、MySQL服务的登录和退出

方式一:通过mysql自带的客户端
只限于root用户

方式二:通过windows自带的客户端
登录:
mysql 【-h主机名 -P端口号 】-u用户名 -p密码

退出:
exit或ctrl+C

3、MySQL的常见命令

1、查看当前所有的数据库
show databases;

2.打开指定的库
use 库名

3.查看当前库的所有表
show tables;

4.查看其它库的所有表
show tables from 库名;

5.创建表
create table 表名(
	列名 列类型,
	列名 列类型,
	。。。
);

6.查看表结构
desc 表名;

7.查看服务器的版本
方式一:登录到mysql服务端
select version();

方式二:没有登录到mysql服务端
mysql --version
或
mysql --V

4、MySQL的语法规范

1.不区分大小写,但建议关键字大写,表名、列名小写

2.每条命令最好用分号结尾

3.每条命令根据需要,可以进行缩进 或换行

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

5、SQL的语言分类

DQL(Data Query Language):数据查询语言
	select 
	
DML(Data Manipulate Language):数据操作语言
	insert 、update、delete
	
DDL(Data Define Languge):数据定义语言
	create、drop、alter
	
TCL(Transaction Control Language):事务控制语言
	commit、rollback

6、SQL的常见命令

1.查看所有的数据库:
show databases; 

2.打开指定的库:
use 库名;

3.显示库中的所有表:
show tables ; 

4.显示指定库中的所有表:
show tables from 库名;

5.创建表:
create table 表名(
	字段名 字段类型,	
	字段名 字段类型
); 

6.查看指定表的结构:
desc 表名; 查看指定表的结构

7.显示表中的所有数据:
select * from 表名;显示表中的所有数据

7、DQL语言的学习

7.1、基础查询

语法:
SELECT 要查询的东西
【FROM 表名】;

类似于Java中 :System.out.println(要打印的东西);
特点:
①通过select查询完的结果 ,是一个虚拟的表格,不是真实存在
② 要查询的东西 可以是常量值、可以是表达式、可以是字段、可以是函数

7.2、条件查询

条件查询:根据条件过滤原始表的数据,查询到想要的数据
语法:
select 
	要查询的字段|表达式|常量值|函数
from 
	表
where 
	条件 ;

7.2.1、分类

一、条件表达式
	示例:salary>10000
	条件运算符:
	> < >= <= = != <>


二、逻辑表达式
示例:salary>10000 && salary<20000


逻辑运算符:
	and(&&):两个条件如果同时成立,结果为true,否则为false
	or(||):两个条件只要有一个成立,结果为true,否则为false
	not(!):如果条件成立,则not后为false,否则为true

三、模糊查询
示例:last_name like 'a%'

%:代表任意多个字符,也包括0个字符

_:代表一个字符,如果要查询的内容也带下划线,例如一个名字为K_ing,要查询名字的第二个字符为_的人,就要用到转义字符,
   可以用\也就是last_name like '_\_%' 
   或者也可以自定义一个$: last_name like '_$_%' escape '$' ,这是自定义个转义符的意思,$可以替换为任意一个随便的字符,只需要在后面用escape 解释一下即可。


四、between and
示例:要查询部门编号在100到120之间的员工信息

以前:
select * from employees where department-id>=100 and department-id<=120;

现在:
select * from employees where department-id between 100 and 120;

注意:
1、使用between and 可以提高语句的简洁度
2、between and 可以包含临界值,完全等价于 >= <=
3、既然完全等价于>= <= 也就意味着,between 和 and 前后的值不能乱写,例如本来是between 100 and 120,就不能写成 between 120 and 100。虽然不会报错,但是查询不到结果

五、in关键字(离散查询)
含义:判断某一字段的值是否属于in列表中的某一项
特点:
1:使用in提高了语句的简洁度
2:in列表的值类型必须统一或兼容
3:in列表里面不能用通配符%或者_
	例子:查询员工的工种编号是 itcast 、 itheima 中的一个员工名

以前:Select last-name from employees where job-id = itcast or job-id = itheima
现在:Select last-name from employees where job-id in( ‘itcast ’, ’itheima’);

六、is null 和 is not null
意义:=或者<>不能用于判断null值
Is null 和 is not null 可以判断null值

例子:查询没有奖金的员工名
Select last-name from employees where bonus is null

例子:查询有奖金的员工名
Select last-name from employees where bonus is not null

七、安全等于 <=>
意义:用于判断是否等于
例子:查询没有奖金的员工名
Select last-name from employees where bonus  <=> null

8、排序查询

1、语法:
select
	要查询的东西
from
	表
where 
	条件
order by 排序的字段|表达式|函数|别名 【asc|desc】

2、特点:
1.Asc是自然顺序,也就是从小到大,desc是从大到小,如果不写,默认是升序
2.order by 子句中可以支持单个或多个字段、表达式、函数、别名
3.order by 子句一般是放在查询语句的最后面,limit子句除外


3、例子:查询员工信息,工资按从高到低排序
Select  * from employees order by salary desc

例子:查询员工信息,先按工资排序,再按部门编号排序(order by 支持多个字段排序)
Select * from employees order by salary asc,department-id desc;

9、常见函数

概念:类似于java中的方法,将一组逻辑语句封装在方法体中,对外暴露方法名
好处:1、隐藏了具体的功能实现细节;2、提高代码的重用性
调用:select 函数名(实参列表) from 表;在函数里面的参数用到表中的字段时,才需要加from 表。
特点:
1、叫什么(函数名)
2、干什么(函数功能)

9.1、单行函数

9.1.1、字符函数

1.concat:拼接
Select concat(lastname,firstname) from employees;

2.Substr或者substring:截取子串
Select substr(‘李莫愁爱上了陆展元’,6);
结果显示:了陆展元
注意:这里的索引是从1开始的,就写一个默认是从6开始之后的全部字符

Select substr(‘李莫愁爱上了陆展元’,1,3);
结果显示:李莫愁
注意:这里的1代表从第一个开始,是索引,3代表字符的长度,不是索引。

例子:名字首字母大写,其他小写,用‘_’拼接
Select concat(upper(substr(lastname,1,1),‘_’,lower(lastname,2))) from employees;

3.upper:转换成大写
Select upper(‘fuxupeng’)

4.lower:转换成小写
Select lower(‘FUXUPENG’)
示例:将姓大写,名小写,然后拼接
Select cancat(upper(lastname),lower(firstname))from employees;


5.trim:去前后指定的空格和字符
Select trim (‘     欧阳    ’);
显示结果:欧阳
空格会消失

Select trim(‘a’from ‘aaaaa欧aa阳aaaaa’);
显示结果:欧aa阳
这样可以去除指定的字符,但是只能去前后的字符

6.ltrim:去左边空格
Select ltrim(‘   欧阳   ’);
显示结果:欧阳   ;
欧阳后面还有三个空格不能去除

7.rtrim:去右边空格
Select rtrim(‘    欧阳    ’);
显示结果:   欧阳;
前面的空格不能去除

8.replace:替换
Select replace(‘欧阳茜是憨憨’,‘憨憨’,‘憨瓜’);
显示结果:欧阳茜是憨瓜

9.lpad用指定字符实现左填充指定长度
Select lpad(‘欧阳’,10,‘*’);
显示结果:********欧阳
欧阳只有两个字符,不满10个,所以在左边填充8个*

Select lpad(‘欧阳’,1,‘*’);
显示结果:欧
最终显示的长度由里面的数字决定

10.rpad用指定字符实现右填充指定长度
Select rpad(‘欧阳’,10,‘*’);
显示结果:欧阳********
欧阳只有两个字符,不满足10个,所以在右边填充8个*

11.instr返回子串第一次出现的索引,如果找不到,返回0
Select instr(‘欧阳茜是个憨憨’,‘憨憨’);
显示结果:6
Select instr(‘憨憨欧阳茜’,‘憨憨’);
显示结果:1

12.length 获取字节个数:
Select length(参数) from 表;如果参数用到表中的字段就加from 表,没有就不加

Ifnull 判断是否为空(因为null+任何东西都为null,当某个字段有些为null,有些不为null的时候,就要加																这个函数用于判断)

9.1.2、数学函数

1.round 四舍五入

Select round(1.65);
显示结果:2

Select round(1.567,2);
显示结果:1.57
小数点后保留两位

2.rand 获取随机数

返回0-1之间的小数

3.floor向下取整(显示小于等于这个数的最大整数)

select floor(1.02)
显示结果:1
Select floor(-1.02)
显示结果:-2

4.ceil向上取整(显示大于等于这个数的最小整数)

Select ceil(1.52)
显示结果:2
Select ceil(1.02)
显示结果:2
Select ceil(1.00)
显示结果:1
Select ceil(-1.2)
显示结果:0

5.mod取余(带负数的求余,只要看被除数就行,余数跟被除数的符号一致)

mod运算:mod(a,b): a-a/bb
Mod(-10,-3):-10-(-10)/(-3)
(-3)=-1
Select mod(10,3)
显示结果:1
Select mod(-10,-3);
显示结果:-1
Select mod(-10,3);
显示结果:-1
Select mod(10,-3);
显示结果:1

6.truncate截断

Select truncate(1.65,1);
显示结果:1.6
不管后面是什么,就取到小数点后几位

9.1.3、日期函数

1.now当前系统日期+时间

Select now();
显示结果:当前计算机的日期和时间
在这里插入图片描述

2.curdate当前系统日期,不包含时间

Select curdate();
在这里插入图片描述

扫描二维码关注公众号,回复: 12678543 查看本文章
3.curtime当前系统时间,不包含日期

Select curtime();
在这里插入图片描述

4.可以获取指定的部分,年、月、日、时、分、秒

Select year(now())as 年;
在这里插入图片描述

Select year(‘1997-08-24’)as 欧阳茜的生日啊;
在这里插入图片描述

Select year(某个表的字段名);

Select month(now());
在这里插入图片描述

Select monthname(now());
在这里插入图片描述

Select day(now());
在这里插入图片描述

Select hour(now());
在这里插入图片描述

5.str_to_date 将日期格式的字符转换成指定格式的日期

select str_to_date(‘1997-08-24’,‘%Y-%c-%d’)

Str_to-date是转化成日期,所以必须是日期格式,不能加上年月日的字符
在这里插入图片描述

6.date_format将日期转换成字符

Select date_format(now(),‘%y年%c月%d日’);
这个是日期转换成字符,最后是转化成字符的,所以可以加上年月日字符。

在这里插入图片描述在这里插入图片描述

9.1.4、流程控制函数

1.if 处理双分支(类似于java的三元运算符)

如果前面的表达式正确,则显示第二个值,否则显示第三个值
Select if(10>5,‘大’,‘小’);

在这里插入图片描述

2.case语句 处理多分支

用法1:等值判断

Java中的switch case:

Switch 要判断的变量或表达式
Case 常量1:语句1;break;

Default:语句n;break;

 Mysql中:

Case 要判断的字段或表达式
When 常量1 then 要显示的值1或语句1;
When 常量2 then 要显示的值2或语句2;(这里的分号,显示的是语句时才要加分号)

Else 要显示的值n或语句n
End

例子:查询员工的工资,要求:
部门号=30,显示的工资为1.1倍
部门号=40,显示的工资为1.2倍
部门号=50,显示的工资为1.3倍
其他部门,显示为原工资

Select salary as 原始工资,dapartment_id 
Case department_id
When 30 then salary*1.1(注意这是个值,所以不能加分号,不然到这里就结束了)
Case department_id
When 40 then salary*1.2
Case department_id 
When 50 then salary*1.3
Else salary
End as 新工资
From employees;

用法2:类似于多重if

Java中:

If(条件1){
语句1;
}else if(条件2){
语句2;
}
........
Else{
语句n;
}

Mysql中:

Case
When 条件1 then 要显示的值1或语句1
When 条件2 then 要显示的值2或语句2
......
Else 要显示的值n或语句n

例子:查询员工的工资情况
如果工资>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 as 工资级别
From employees;

9.1.5、其他函数

1.version版本

Select version();
在这里插入图片描述

2.database当前库

select database();
在这里插入图片描述

3.user当前连接用户

select user();

在这里插入图片描述

9.2、分组函数

1、功能:用作统计使用,又称为聚合函数或者统计函数或组函数

9.2.1、sum 求和

Select sum(salary) from employees;
求某个字段的和

9.2.2、max 最大值

Select max(salary) from employees;
求某个字段的最大值

9.2.3、min 最小值

Select min(salary) from employees;
求某个字段的最小值

9.2.4、avg 平均值

Select avg(salary) from employees;
求某个字段的平均值

9.2.5、count 计数

Select count(salary) from employees;
求某个字段的个数

9.2.6、多个一起使用

select sum(salary) as 和,avg(salary) as 平均值,max(salary) as 最大值…

9.2.7、特点:

	1、以上五个分组函数都忽略null值,除了count(*)
	2、sum和avg一般用于处理数值型
		max、min、count可以处理任何数据类型
    3、都可以搭配distinct使用,用于统计去重后的结果
	4、count的参数可以支持:
	   字段、*、常量值,一般放1(其实任何值都可以,哪怕是字符型都可以,它相当于在每一行的前面都加了一个1或者字符,然后count统计的时候,是在统计1的个数或者字符的个数),建议使用 count(*)

在MYISAM的引擎下,count(*)的效率要高,在MYISAM的内部就有一个计数器,可以直接返回。
在INNODB的引擎下,count(*)和count(1)的效率差不多,比count(字段)要高

5、注意:和分组函数一同查询的字段有限制
Select avg(salary),last-name from employees;
虽然这个语句不会报错,但是avg是求平均值,所以最后查询出来的只有一行,数据库显示的结果是规则的表格,所以	last-name也会出现一个值,正常来说,avg只有一个数值,但是last-name应该有所有的值,但是为了规则表格,last-name也只显示了一个值,但是这个值是没有任何意义的。

和分组函数一同查询的字段要求是group by后的字段,其他的都不行。

10、查询

10.1、分组查询(group by)

10.1.1、语法:

select 分组函数,查询的字段(要求出现在group by后面)
from 表
【where 条件】
group by 分组的字段
【order by子句】

10.1.2、举例

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

Select max(salary),job-id
From employees
Group by job-id

例子2:查询不同的部门个数

Select count(*),department-id
From employees
Group by department-id

10.1.3、添加分组前的筛选条件

例子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 bonus is not null
Group by manager-id

10.1.4、添加分组后的筛选条件

例子1:查询哪个部门的员工人数大于2

1、查询每个部门的员工人数
Select count(*),department-id
From employees
Group by department-id;

2、根据1的结果进行筛选,查询哪个部门的员工人数大于2
Select count(*),department-id
From employees
Group by department-id
Having count(*)>2;

注意:这里不能用where条件,比如说:

Select count(*),department-id
From employees
Where count(*)>2
Group by department-id;
Where后面的条件必须是那张表里面有这个字段,而count(*)这个字段在原始表里面并不存在,所以不能用where筛选	条件,只能在后面用having

例子:查询每个工种有奖金的员工的最高工资>12000的工种编号及其最高工资

1、查询每个工种有奖金的员工的最高工资
Select max(salary),job-id
From employees
Where bonus is not null
Group by job-id;

这里的bonus在原始表中是存在的,所以可以使用where条件

2、根据1的结果继续筛选,最高工资>12000
Select max(salary),job-id
From employees
Where bonus is not null
Group by job-id
Having max(salary)>12000;

这里的max(salary)在原始表中并不存在,所以只能使用having

3、按表达式或者函数分组
例子:按员工姓名长度分组,查询每一组的员工人数,筛选员工人数>5的有哪些
1、查询每个长度的员工人数
select count(*),length(last-name)
From employees
Group by length(last- name);

2、添加筛选条件
select count(*)as 人数,length(last-name)
From employees
Group by length(last- name)
Having 人数>5;

注意:Having是支持别名的

4、按多个字段分组
例子:查询每个部门每个工种员工的平均工资
Select avg(salary),department-id,job-id
From employees
Group by department-id,job-id;

注意:Group by 后面的字段顺序可以改变

10.1.5、特点

1、可以按单个字段分组
2、和分组函数一同查询的字段最好是分组后的字段
3、分组筛选
		         针对的表	           位置			     关键字
分组前筛选:	原始表		       group by的前面		 where
分组后筛选:	分组后的结果集	   group by的后面		 having

4、可以按多个字段分组,字段之间用逗号隔开,没有顺序要求,也可以支持表达式和		函数
5、可以支持排序(order by子句放在最后)
6、having后可以支持别名
7、分组函数做条件一定是放在having子句中
8、能用分组前筛选的就优先使用分组前筛选,性能会高一点

10.1.6、添加排序

例子:查询每个部门每个工种员工的平均工资,并且按平均工资的高低进行排序

Select avg(salary),department-id,job-id
From employees
Group by department-id,job-id
Order by avg(salary) desc;

10.2、多表连接查询

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

10.2.1、出现的问题:

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

在这里插入图片描述

比如:有一张表是女生有n个,一张表是男生有m个,一个女生匹配一个男朋友,
这时候,如果这样去写sql语句:
Select name,boyname from girls,boys
这样写是不会不错的,也能查询出结果,只是这个结果是没有意义的。
结果显示:一个女生去匹配每一个男朋友,也就是说一个女生有m个男朋友,这 样就与原来的要求不符合。

解决办法:添加上连接条件
Select name,boyname from girls,boys
Where girls.boyfriend-id=boys.id; 

注意:这里的连接条件不是乱加的,这个连接条件要么是两张表里面一样的字段,要 么就是某一个表中的某个字段匹配值来自于另一张表的某个字段,也就是两 张表中的两个字段要产生联系才行。

10.2.2、分类

10.2.2.1、按年代分

Sql92标准:仅支持内连接
Sql99标准:(推荐使用)支持内连接+外连接(左外、右外)+交叉连接

10.2.2.2、sql92标准

1.内连接:

1.1.等值连接

例子1:查询女生名和对应的男生名
Select name,boyname from girls,boys
Where girls.boyfriend-id=boys.id; 

例子2:查询员工名和对应的部门名
Select last-name,department-name from employees,departments
Where employees.department-id=departments.department-id;

每次我们查询的时候都要用表名.字段名,如果查询的表多了,而且表名 可能都比较长,这样就会很麻烦,所以我们可以为表起一个别名。

例子3:查询员工名、工种号、工种名
Select last-name,employees.job-id,job-title
From employees,jobs
Where employees.job-id=jobs.job-id

可以写成:

Select last-name,e.job-id,job-title
From employees as e,jobs as j
Where e.job-id=j.job-id

注意:如果表使用了别名,那查询的字段就不能用原来的表名去限定,否则报错,from后面的表的顺序可以随意

等值连接可以加筛选吗?

例子4:有奖金的员工名、部门名
Select last-name,department-id
From employees e,departments d
Where e.department-id=d.department-id
And e.bonus is not null;

1.2.非等值连接

例子:查询员工的工资和工资级别
Select salary,grade-level
From employees e,job-grades j
Where salary between j.lowest-sal and j.hightest-sal;

1.3.自连接:

与等值连接类似,只是自连接是在一张表中的。

注意:传统模式下的连接 :等值连接——非等值连接

1.等值连接的结果 = 多个表的交集
2.n表连接,至少需要n-1个连接条件
3.多个表不分主次,没有顺序要求
4.一般为表起别名,提高阅读性和性能
10.2.2.3、sql99语法:通过join关键字实现连接

语法:

select 查询列表 
	from 表1 【连接类型】       (连接类型就是内连接,外连接这些类型)
	【inner|left outer|right outer|cross】join 表2 on  连接条件
	【inner|left outer|right outer|cross】join 表3 on  连接条件
	【where 筛选条件】
	【group by 分组字段】
	【having 分组后的筛选条件】
	【order by 排序的字段或表达式】

含义:1999年推出的sql语法
支持:
内连接:inner(等值连接、非等值连接)
外连接(左外(left 【outer】)、右外(right 【outer】)、全外(full 【outer】))
交叉连接(cross)

10.2.2.3.1、sql99内连接

1、语法:

Select 查询列表
From 表1 别名
Inner join 表2 别名
On 连接条件;

2、分类

2.1.等值连接:

例子1:查询员工名,部门名
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 locaotions l
On d.locaotion-id=l.location-id
Group by city
Having 部门个数>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的基础上筛选员工个数>3的记录,并排序
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(*)asc;

例子5:查询员工名、部门名、工种名、并按部门名排序(三表连接)
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 e.job-id=j.job-id
Order by department-name desc;

特点:

1、可以添加排序,分组,筛选
2、Inner可以省略
3、筛选条件放在where后面,连接条件放在on的后面,提高分离性,便于阅读
4、Inner join连接和sql92语法中的等值连接最终的效果是一样的

2.2.非等值连接:

例子1:查询员工的工资级别
Select salary,grade-level
From employees e
Inner join job-grades j
On e.salary between j.loweat-sal and j.hightest-sal;

例子2:查询工资级别的个数>2的个数,并按工资级别降序
Select count(*),grade-level
From employees e
Inner join job-grades j
On e.salary between j.loweat-sal and j.hightest-sal;
Groupe by grade-level
Having count(*)>2
Order by grade-level desc;

2.3.自连接:

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

sql99语法:

SELECT e.last_name,m.last_name
FROM employees e
JOIN employees m ON e.`manager_id`=m.`employee_id`;

sql92:语法

SELECT e.last_name,m.last_name
FROM employees e,employees m 
WHERE e.`manager_id`=m.`employee_id`;
10.2.2.3.2、sql99外连接
1、应用场景:用于查询一个表中有,另一个表中没有的记录

在这里插入图片描述
这两个表中有关系的字段就是beauty表中的boyfriend-id和boys表中的id,这两个可以相对应,但是,boyfriend-id有8,9这两个值,但是在boys表中却没有,这个时候就可以用到外连接。

2、特点:

1、外连接的查询结果为主表中的所有记录,如果从表中有和主表匹配的,则显示
如果从表中没有和主表匹配的,则显示null
外连接的查询结果=内连接查询结果+主表中有而从表中没有的记录
2、如何区分主从表
	左外连接:left join左边的是主表
	右外连接:right join右边的是主表
3、左外和右外交换两个表的顺序,可以实现同样的效果
4、全外连接=内连接的结果+表1中有但表2中没有的记录+表1中没有但表2中有的记录

3、引入:查询男朋友不在男生表中的女生名
左外连接:

Select b.name,bo.*
From beauty b
Left outer join boys bo
On b.boyfriend-id=bo.id;

在这里插入图片描述

右外连接:

Select b.name,bo.*
Fromboys bo
Right outer join beauty b
On b.boyfriend-id=bo.id;
10.2.2.3.3、全外连接

全外连接可以查出三部分,一部分是多表中的交集部分,一部分是主表中不能与从表匹配到记录,还有一部分是从表中不能与主表匹配到的部分。

10.2.2.3.4、交叉查询
Select b.*,bo.*
From beauty b
Cross join boys bo;

在这里插入图片描述

交叉查询其实就是一个笛卡尔乘积,女生表有11行数据,男生表有4行数据,用了交叉查询后就是44行数据。

10.3、子查询

10.3.1、含义

出现在其他语句(包括所有的语句)中的select语句,称为子查询或内查询
在外面的查询语句,称为主查询或外查询
在这里插入图片描述

10.3.2、分类

1、按子查询出现的位置

Select后面:
只支持标量子查询

From后面:
表子查询

Where或者having后面:
标量子查询
列子查询
行子查询(用的比较少)

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

2、按结果集的行列数不同

标量子查询(结果集只有一行一列)
列子查询(结果集只有一列多行)
行子查询(结果集可以是多行多列,主要是一行多列)
表子查询(结果集随意,只要是查询结果即可,一般Wie多行多列)

10.3.3、where和having后面

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

例子:谁的工资比Abel高
(1)、查询名字为Abel的工资
Select salary from employees where last-name=‘Abel’;
(2)、查询员工信息,满足salary>1出现的结果
Select * from employees where salary>(Select salary from employees where 	last-name=‘Abel’);

例子2:返回job-id和141号员工相同,salary比143号员工多的员工姓名,job-id和工资
(1)、查询141号员工的job-id
Select job-id from employees where employee-id=141;

(2)、查询143号员工的工资
Select salary from employees where employee-id=143;

(3)、查询员工的姓名,job-id,工资,要求jiob-id=(1)的结果且salary>(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
(1)、查询公司的最低工资
Select min(salary)from employees;

(2)、查询员工的last-name,job-id,salary,要求salary=(1)的结果
Select last-name,job-id,salary from employees where salary=(Select min(salary)from employees);

例子4:查询最低工资>50号部门最低工资的部门id和其最低工资
(1)、查询50号部门的最低工资
Select min(salary)from employees where department-id=50;

(2)、查询每个部门的最低工资
Select min(salary),department-id from employees 
Group by department-id;

(3)、在(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:返回locaotion-id是1400或1700 部门中的所有员工姓名
(1)、查询location-id是1400或1700的部门编号
Select department-id from departments where location-id in(1400,1700);
(2)、查询员工姓名,要求部门号是(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
(1)、查询job-id为‘it-prog’部门的任一工资
Select salary from employees where job-id=‘it-prog’;

(2)、查询员工号、姓名、job-id以及salary,要求salary<(1)的结果
Select last-name,employee-id,job-id,salary from employees where salary 	<any(Select salary from employees where job-id=‘it-prog’)and job-id<>	‘it-prog’;

例子3:返回其他工种中比job-id为‘it-prog’工种所有工资都要低的员工的员工号、姓名、job-id以及salary
Select last-name,employee-id,job-id,salary from employees where salary <all(Select salary from employees where job-id=‘it-prog’)and job-id<>	‘it-prog’

3、行子查询(结果集一行多列或多行多列)

例子1:查询员工编号最小并且工资最高的员工信息
以前:
(1)、查询员工编号最小
Select min(employee-id)from employees;
(2)、查询最高工资

Select max(salary)from employees;

(3)、查询员工信息
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);

注意:行子查询有局限性,只有当要查询的语句都是用“=”的时候,才能使 用行自查询,所以一般不用行子查询。

特点:

1、子查询都放在小括号内
2、子查询可以放在from后面、select后面、where后面、having后面,但一般放在条件的右侧
3、子查询优先于主查询执行,主查询使用了子查询的执行结果
4、子查询根据查询结果的行数不同分为以下两类:
① 单行子查询
	结果集只有一行
	一般搭配单行操作符使用:> < = <> >= <= 
	非法使用子查询的情况:
	a、子查询的结果为一组值
	b、子查询的结果为空
	
② 多行子查询
	结果集有多行
	一般搭配多行操作符使用:any、all、in、not in

在这里插入图片描述

	in: 属于子查询结果中的任意一个就行
	any和all往往可以用其他查询代替

10.3.4、select后面(只支持标量子查询)

例子1:查询每个部门的员工个数
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.department-id 
where e.employee-id =102 );

10.3.5、from后面

例子:查询每个部门的平均工资的工资等级
(1)、查询每个部门的平均工资
Select avg(salary),department-id
From employees
Group by department-id;

(2)、查询工资登记
Select * from job-grades;

(3)、连接(1)和(2)的结果集,筛选条件平均工资between lowest-sal and highest-sal 
Select ag-dep.*,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;

10.3.6、exists后面(相关子查询)

Select exists(select employee-id from employees);
查询结果为1

Select exists(select employee-id from employees where salary=3000000000);
查询结果为0

这个查询只判断子查询的结果是否存在,存在就显示,不存在就显示0

例子1:查询有员工的部门名
Select department-name
From departments d
Where exits(
Select * from employees e
Where e.department-id = d.department-id
);

10.4、分页查询

10.4.1、应用场景

实际的web项目中需要根据用户的需求提交对应的分页查询的sql语句,一页显示不全

10.4.2、语法

select 字段|表达式,...
from 表
【jion type】 jion 表2
【where 条件】
【group by 分组字段】
【having 条件】
【order by 排序的字段】
limit 【起始的条目索引】条目数;

10.4.3、例子

查询前5条员工信息
Select * from employees limit 0,5;

如果起始的索引是从第一条开始的,可以省略0:
Select * from employees limit 5;

查询第11到25条员工信息
Select * from employees  limit 10,15;

有奖金的员工信息,并且工资较高的前10名
Select * from employees where bonus is not null 
Order by salary desc
Limit 10;

10.4.4、特点

1.起始条目索引从0开始

2.limit子句放在查询语句的最后

3.公式:select * from  表 limit (page-1)*sizePerPage,sizePerPage
假如:
每页显示条目数sizePerPage
要显示的页数 page

10.5、联合查询

10.5.1、引入

union 联合、合并,讲多条查询语句的结果合并为一个结果

10.5.2、语法

select 字段|常量|表达式|函数 【from 表】 【where 条件】 union 【all】
select 字段|常量|表达式|函数 【from 表】 【where 条件】 union 【all】
select 字段|常量|表达式|函数 【from 表】 【where 条件】 union  【all】
.....
select 字段|常量|表达式|函数 【from 表】 【where 条件】

10.5.3、例子

查询部门编号>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;

注意:当要查询的字段来自多个表,且这两个表没有联系(之前学习的join 也可以连接两张表,但是用join之类的关键词所连接的两张表是有联系的,他们的某一个字段是相同的,而这里的union是当两张表完全没有任何联系的时候,才使用),但是查询的信息一致时(例如,有国外和国内的人们的一张表,要查询国外的男性人数和国内的男性人数,当查询的信息一致时,才可使用),可以用union关键字将他们的查询结果合并为一个查询结果,方便查看。

10.5.4、特点

1、多条查询语句的查询的列数必须是一致的(select后面查询的字段要一样多)
2、多条查询语句的查询的列的类型和顺序最好相同
3、union代表去重,union all代表不去重(查询的两个表中可能有重复的)

三、DML语言

1、插入

1.1、语法

insert into 表名(字段名,...)
values(值1,...);

1.2、特点

1、字段类型和值类型一致或兼容,而且一一对应
2、可以为null的字段,可以不用插入值,或用null填充
3、不可以为null的字段,必须插入值
4、字段个数和值的个数必须一致
5、如果insert into 后面的字段名省略了,那values里面的值就要把这张表里面的所有		都添加一遍,且要按字段顺序和类型一次添加。

2、修改

修改单表语法:重点

update 表名 set 字段=新值,字段=新值
【where 条件】

修改多表语法:非重点
Sql92:

	update 表1 别名1,表2 别名2
	set 字段=新值,字段=新值
	where 连接条件
	and 筛选条件

Sql99:

Update 表1 别名
Inner/left/right join 表2 别名
On 连接条件
Set 字段=新值,.....
Where 筛选条件

例子:修改张无忌的女朋友的手机号为114
Update boys bo
Inner join beauty b
On bo.‘id’ = b.‘boyfriend-id’
Set b.‘phone’=‘114’
Where bo.‘boyname’=‘张无忌’;

3、删除

方式1:delete语句

单表的删除: ★

delete from 表名 【where 筛选条件】

多表的删除:不重要

delete 别名1,别名2
from 表1 别名1,表2 别名2
where 连接条件
and 筛选条件;

方式2:truncate语句

truncate table 表名

两种方式的区别【面试题】

1.truncate不能加where条件,而delete可以加where条件

2.truncate的效率高一丢丢

3.truncate 删除带自增长的列的表后,如果再插入数据,数据从1开始
delete 删除带自增长列的表后,如果再插入数据,数据从上一次的断点处开始

4.truncate删除不能回滚,delete删除可以回滚

在这里插入图片描述

四、DDL语句

1、库和表的管理

1.1、库的管理

一、创建库
create database 【if not exists】 库名 

二、删除库
drop database 【if exists】库名

三、更改库的字符集(暂时更改)
Alter database 库名 character set 字符集
想要永久改变字符集,需要在配置文件里面修改

1.2、表的管理

1、语法:

CREATE TABLE IF NOT EXISTS 表名(
字段名 字段的类型【长度,约束】,
字段名 字段的类型【长度,约束】,
....
字段名 字段的类型【长度,约束】

);

2、创建表

CREATE TABLE IF NOT EXISTS stuinfo(
	stuId INT,
	stuName VARCHAR(20),
	gender CHAR,
	bornDate DATETIME
);

DESC studentinfo;

2、修改表 alter

语法:

ALTER TABLE 表名 ADD|MODIFY|DROP|CHANGE COLUMN 字段名 【字段类型,约束】;

注意:COLUMN可以省略不写,建议都写上

①修改字段名

ALTER TABLE 表名 CHANGE  COLUMN 原字段名 修改的字段名 字段类型;

ALTER TABLE studentinfo CHANGE  COLUMN sex gender CHAR;

②修改表名

ALTER TABLE 原表名 RENAME [TO]  修改的表名;

ALTER TABLE stuinfo RENAME [TO]  studentinfo;

③修改字段类型和列级约束

ALTER TABLE 表名 MODIFY COLUMN 字段名 字段类型 ;

ALTER TABLE studentinfo MODIFY COLUMN borndate DATE ;

④添加字段

ALTER TABLE 表名 ADD COLUMN 字段名 字段类型 【first】;
ALTER TABLE studentinfo ADD COLUMN email VARCHAR(20) 【first】;

注意:加了first 就是在所有字段的最前面添加这个字段
在这里插入图片描述

⑤删除字段

ALTER TABLE 表名 DROP COLUMN字段名;
ALTER TABLE studentinfo DROP COLUMN email;

3、删除表

DROP TABLE [IF EXISTS] studentinfo;

4、表的复制

4.1、仅复制表的结构

Create table 新表名 like 被复制的表名
Create table copy like books;

4.2、复制表的结构+数据

Create table 新表名 
Select * from 被复制的表名;

Create table copy2 select * from books;

4.3、复制部分数据

Create table 新表名
Select 要复制的字段名1,... from 被复制的表名 where 筛选条件;

Create table copy3 select id,name,author from books where sex=‘男’;

4.4、仅仅复制某些字段,不要数据

Create table 新表名 
Select 要复制的字段名1,...
From 被复制的表名
Where 1=2;

Create table copy4 select id,name from books where 1=2;

在where条件恒为假的时候,数据是不会复制过去的

4.5、蠕虫复制

在这里插入图片描述

5、常见类型

数值型
整型:
在这里插入图片描述

小数:
在这里插入图片描述

注意:M和D的意思(M和D可以省略不写)
M:整数部分+小数部分一共的长度
D:小数部分的长度
如果超过了范围,则插入临界值

字符型:
在这里插入图片描述

较短的文本:char,varchar
1、M的意思是最大字符数,char的M可以省略不写,默认为1,varchar不能 省略。
2、Char是固定长度的字符,耗空间,高性能;varchar是可变长度的字符,省 空间,低性能。

较长的文本:text,Blob类型(较长的二进制数据)

日期型:
在这里插入图片描述

Datetime和timestamp的区别:
在这里插入图片描述

6、常见约束

6.1、含义

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

6.2、分类

NOT NULL 			非空,用于保证该字段的值不能为空
DEFAULT				默认,用于保证该字段的默认值
UNIQUE				唯一,用于保证该字段的值具有唯一性,可以为空
CHECK				检查,(mysql中不支持)
PRIMARY KEY			主键:用于保证该字段的值具有唯一性,不能重复,且非空
FOREIGN KEY			外键:用于限制两个表的关系,用于保证该字段值必须来自于主							  表的关联列的值,在从表添加外键约束,用于引用主表中							  某列的值
Comment				说明:用于对该字段进行注释说明
Auto_increment 		自增:用于该字段自动增加其值
Zerofill			0填充:未达到规定长度的数值,其数值前用0填充
Unsigned			无符号:即只有正数

注意:这些约束可以同时使用多个,用空格隔开。
在这里插入图片描述

6.3、添加约束的时机

1.创建表时
2.修改表时

6.4、约束的添加分类

1.列级约束:六大约束语法上都支持,但外键约束没有效果
2.表级约束:除了非空、默认,其他都支持

6.5、建表时添加列级约束

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 20,
Majorid int foreign key references major(id)
);

Create table major(
Id int primary key,
Majorname carchar(20)
);

6.6、建表时添加表级约束

Create table stuinfo(
Id int ,
Stuname varchar(20),
Gender char(1),
Seat int ,
Age int,
Majorid int,

Constraint pk primary key(id),
Constraint uq unique(seat),
Constraint fk-stuinfo-major foreign key(majorid) references major(id)

);

注意:Constraint 别名 可以省略不写。

7、主键和唯一键的区别

在这里插入图片描述

允许组合的意思是:primary key(字段1,字段2)或者 unique(字段1,字段2)
这两个约束都是不能重复的,但是组合之后,如果插入的两个值只是字段1或者字段2的信息一样,是不会报错的,只有当字段1和字段2都插入重复的值才会报错。

8、外键

1、要求在从表中设置外键关系
2、从表的外键列的类型和主表的关联列的类型要求一致或兼容,名称无要求
3、主表的关联列必须是一个key(一般是主键或唯一键),如果不是一个key的话,是无法	建立外键约束的。
4、插入数据时,先插入主表,再插入从表;删除数据时,先删除从表,再删除主表。

9、修改表时添加约束

9.1、添加非空约束

 Alter table 表名 modify column 字段名 字段类型  not null;

9.2、添加默认约束

Alter table 表名 modify column 字段名 字段类型  dafault (值);

9.3、添加主键

9.3.1、列级约束的写法

Alter table 表名 modify column 字段名 字段类型  primary key ;

9.3.2、表级约束的写法

Alter table 表名 ADD primary key(字段名);

9.4、添加唯一约束

9.4.1、列级约束的写法

Alter table 表名 modify column 字段名 字段类型  unique ;

9.4.2、表级约束的写法

Alter table 表名 ADD  unique (字段名);

9.5、添加外键

Alter table 表名 add 【constraint 别名】 foreign key(从表的字段名) references 主表名(关联字段);

10、修改表时删除约束

10.1、删除非空约束

Alter table 表名 modify column 字段名 字段类型 【null】;

这里null不写也可以,因为要删除非空就是变为空,写了null就正好相反,或者不写,就是默认,默认也是null。

10.2、删除默认约束

Alter table 表名 modify column 字段名 字段类型 ;

10.3、删除主键

Alter table 表名 drop primary key ;
或者:
Alter table 表名 modify column 字段名 字段类型

10.4、删除唯一键

Alter table 表名 drop index 唯一键的字段 ;

唯一键的字段可以通过:show index from 表名 查出来,哪个是有唯一键的字段。

10.5、删除外键

Alter table 表名 drop foreign key 外键的别名 ;

11、标识列

标识列又称为自增长列,可以不用手动插入值,系统提供默认的序列值,从1开始

11.1、创建表时设置标识列

1、语法:

Create table 表名 (
字段名 字段类型 约束 aotu_increment,
字段名 字段类型 约束,
......
);

2、例子:

Create table test (
Id int primary key aotu_increment;
Name varchar(20)
);

插入值

Insert into test values(1,’john’);

如果这时候还要插入第二条值,Insert into test values(2,’lily’);这里的id这个值就要手动去改,因为id是主键,不能重复,我们需要手动去改,如果有很多数据的话,每次都要手动改就会很麻烦,这个时候就用到了标识列:aotu_increment。

当用到标识列的时候,一般是用在int类型上,我们添加数据的时候,就不能Insert into test values(1,’john’);这样去添加,应该Insert into test values(null,’john’);或者Insert into test values(’john’);这样去添加,这样的话,就会使自增的那个列,自动增加。

注意:
通过show variables like ‘%aotu_increment%’;来查看

在这里插入图片描述

第一行是偏移量,也就是每次增长多少
第二行是从哪个值开始自增
所以我们可以通过设置来实现需要的自增模式,但是mysql中不支持设置起始量,也就是刚开始的值肯定是1,只能设置偏移量:
Set aotu_increment_increment =3;
在这里插入图片描述

前面说到了起始值是不能设置的,mysql不支持,但是也可以用另外一种方法来设置起始值
这是一种取巧的方法:
就是在最开始插入值的时候,Insert into test values(1,’john’),在id的位置,先自己设置一个值,这个值就是自己想要的起始值,然后再插入其他值,Insert into test values(null,’john’),这里的id的位置用null或者不写,这样就能实现改变起始值了。

11.2、特点

1、标识列必须和主键搭配吗?不一定,但要求必须是一个key,例如主键,唯一,外键,以后还能自己定义key。
2、一个表中至多只能有一个标识列
3、标识列的类型只能是数值型,int,float,double
4、标识列可以通过Set aotu_increment_increment =3;设置偏移量,也可以通过手动插入值	来改变起始值

11.3、修改表时设置标识列

语法:

Alter table 表名 modify column 字段名 字段类型 约束类型 aotu_increment;

11.4、修改表时删除标识列

语法:

Alter table 表名 modify column 字段名 字段类型 ;

五、数据库事务(TCL语言)

1、含义

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

在这里插入图片描述

2、特点(ACID)

原子性:要么都执行,要么都不执行
一致性:保证数据的状态操作前和操作后保持一致
隔离性:多个事务同时操作相同数据库的同一个数据时,一个事务的执行不受其他			事务的干扰
持久性:一个事务一旦提交,则数据将持久化到本地,除非其他事务对其进行修改

在这里插入图片描述

相关步骤:

1、开启事务
2、编写事务的一组逻辑操作单元(多条sql语句)
3、提交事务或回滚事务

3、事务的分类

3.1、隐式事务

没有明显的开启和结束事务的标志

比如
insert、update、delete语句本身就是一个事务

3.2、显式事务

具有明显的开启和结束事务的标志

前提:必须先设置自动提交功能为禁用。

Show variables like ‘aotucommit’;

在这里插入图片描述

Set aotucommit=off;
或者
Set aotucommit=0;

3.3、步骤

3.3.1、开启事务

Set aotucommit =0;
Start transaction;可选,可写可不写

3.3.2、编写事务中的sql语句

这里的语句一般就是:select、insert、update、delete
语句1;
语句2;
...

3.3.3、结束事务

1、确定事务没问题可以提交了:commit;
2、事务出现了问题,进行回滚:rollback;

演示:
Jhon和lily都有1000元,jhon向lily转了500元

开启事务:

Set aotucommit =0;
Start transaction;

编写语句:

Update test set money=500 where name=‘jhon’;
Update test set money=1500 where name =‘lily’;

结束事务:

Commit;

3.4、savepoint的使用

savepoint 节点名;设置保存点,只能搭配rollback使用。

在这里插入图片描述

这里有两条语句,删除id为25和28的数据,但是在这两条语句中间设置了一个保存 点a,最后rollback to a,就是回滚到a处,id为28的数据在保存点a之后,所以这条 数据不会被删除成功。
在这里插入图片描述

3.5、事务的隔离级别

3.5.1、事务并发问题如何发生

当多个事务同时操作同一个数据库的相同数据时

3.5.2、事务的并发问题有哪些

脏读:一个事务读取到了另外一个事务未提交的数据
不可重复读:同一个事务中,多次读取到的数据不一致
幻读:一个事务读取数据时,另外一个事务进行更新,导致第一个事务读取到了没有更 新的数据
在这里插入图片描述

3.5.3、如何避免事务的并发问题

在这里插入图片描述
1、通过设置事务的隔离级别:

在这里插入图片描述

	1.READ UNCOMMITTED 都不能避免
	2.READ COMMITTED 可以避免脏读
	3.REPEATABLE READ 可以避免脏读、不可重复读和一部分幻读
	4.SERIALIZABLE可以避免脏读、不可重复读和幻读

2、设置隔离级别:
set session(当前mysql的级别)| global(全局的级别) transaction isolation level 隔离级别名;

3、查看隔离级别:

select @@tx_isolation;

在这里插入图片描述

六、视图

1、含义

理解成一张虚拟的表,和普通表一样使用

例子:查询姓张的学生名和专业名(学生名和专业名来自两张表)
以前:select stu-name,major-name
  From students s
  Inner join majors m
  On s.majorid = m.id
  Where s.stu-name like ‘张%’;


用视图以后:
先创建一个视图,将复杂的那一部分全部扔到视图里
Create view v1
As
select stu-name,major-name
From students s
Inner join majors m
On s.majorid = m.id
查询:
Select * from v1 where stu-name like ‘张%’;

2、视图和表的区别

		使用方式			占用物理空间

视图		完全相同			不占用,仅仅保存的是sql逻辑

表	    完全相同			占用

3、视图的好处

1、sql语句提高重用性,效率高
2、和表实现了分离,提高了安全性
3、保护数据,提高安全性

4、视图的操作

4.1、创建视图

1、语法

Create view 视图名
As
查询语句;

2、例子

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 * from v1 where last-name like‘%a%’;


2.查询各部门的平均工资级别 
①、创建视图查看每个部门的平均工资
Create view v2
As
Select avg(salary)ag ,department-id
From employees e
Group by department-id
②、使用①的结论
Select v2.ag,g.grade-level
From v2
Join jobs g
On v2.ag between g.heighest-sal and g.lowest-sal;

3.查询平均工资最低的部门信息 
使用上面2的平均工资
Select* form v2 order by ag limit 1;




4.查询平均工资最低的部门名和工资
Create view v3
As
Select* form v2 order by ag limit 1;

Select d.*,v3.ag
From v3
Join departments d
On d.department-id=v3.department-id;

4.2、视图数据的增删改查

1、查看视图的数据 ★

SELECT * FROM 视图名;
SELECT * FROM 视图名 条件语句;

2、插入视图的数据
INSERT INTO 视图名(字段名1、字段名2,....) VALUES(对应的值.....);
对原始表也会进行更新,原始表里也会有插入的这条数据

3、修改视图的数据

UPDATE 视图名 SET last_name ='梦姑' WHERE last_name='虚竹';
对原始表也可以更新

4、删除视图的数据
DELETE FROM 视图名;

原始表里也会被删除

注意:一般是不会对视图数据进行操作的,实际中,一般会给视图加权限,让视图只 能读不能写,这样就不会对原始表产生影响,保证了安全性。

4.3、某些视图不能更新

1、包含以下关键字的sql语句:分组函数、distinct、group by、having、union或者union all

2、常量视图

Create view v1 
As
Select ‘john’ name;
Select后面就直接是一个常量的视图,就叫做常量视图。

Update v1 set name =‘lily’;
这是会报错的

3、Select中包含子查询

Create view v2
As
Select (select count(*)from employees); 
这里用update更新也会报错,v2里面的数据不允许被更新

4、join

Create view v3
As
Select last-name,department-id
From employees e
Join departments d
On e.department-id=d.department-id;
这里也不能用update更新v3里面的数据

5、from一个不能更新的视图

Create view v4
As
Select * from v2
这个v2视图在上面是属于不能更新的视图,所以v4里面的数据也不能更新

6、where子句的子查询引用了from子句中的表

Create view v5
As
Select last-name,email
From employees e
Where employee-id in(
Select manager-id
From employees
Where manager-id is not null
);

v5里面的数据也不允许被更新

4.4、视图的修改

方式一:

CREATE OR REPLACE VIEW 视图名
AS
查询语句;	
意思是如果视图存在则修改,如果不存在,则创建


方式二:
ALTER VIEW视图名
AS
查询语句;	

4.5、视图的删除

DROP VIEW 视图名1,视图名2,...;

4.6、视图结构的查看

DESC 视图名;
SHOW CREATE VIEW视图名\G;

\G的作用就是将显示出来的结果格式化一下,便于观察

七、变量

1、系统变量

变量由系统提供,不是用户定义的,属于服务器层面上的

1.1、全局变量

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

1、查看所有全局变量
SHOW GLOBAL VARIABLES;

2、查看满足条件的部分系统变量
SHOW GLOBAL VARIABLES LIKE ‘%char%’;

3、查看指定的系统变量的值
SELECT @@global.系统变量名;
不写默认是session

4、为某个系统变量赋值
第一种:SET @@global.系统变量名=值;
第二种:SET GLOBAL 系统变量名=值;

注意:全局变量可以跨连接,在一个连接中设置好的全局变量,在打开几个连接,这个全 局变量都是已经改变的值

1.2、会话变量

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

1、查看所有会话变量
SHOW SESSION VARIABLES;
Session可以不写,默认就是session

2、查看满足条件的部分会话变量
SHOW SESSION VARIABLES LIKE ‘%char%’;

3、查看指定的会话变量的值
SELECT @@系统变量名;
SELECT @@session.系统变量名;

4、为某个会话变量赋值
第一种:SET @@session.系统变量名=值;
第二种:SET SESSION 系统变量名=值;

2、自定义变量

变量是用户自定义的,不是系统提供的
步骤:声明、赋值、使用(查看,比较,运算)

2.1、用户变量

作用域:针对于当前会话(连接)有效,同于会话变量的作用域
应用在任何地方,也就是放在begin end的里面或者外面
1、声明并初始化:

第一种:SET @变量名=值;
第二种:SET @变量名:=值;
第三种:SELECT @变量名:=值;

2、赋值:

方式一:一般用于赋简单的值
	SET  @变量名=值;
	SET  @变量名:=值;
	SELECT  @变量名:=值;

方式二:一般用于赋表中的字段值
	SELECT 字段名或表达式 INTO 变量名
	FROM 表;

3、使用(查看用户变量的值):
select @用户变量名;

2.2、局部变量

作用域:仅仅在定义它的begin end中有效
应用在begin end中的第一句话!!!

1、声明:
declare 变量名 类型 【default 值】;

2、赋值:

方式一:一般用于赋简单的值
SET 变量名=值;
SET 变量名:=值;
SELECT @变量名:=值;

方式二:一般用于赋表 中的字段值
SELECT 字段名或表达式 INTO 变量
FROM 表;

3、使用:

select 变量名

3、二者的区别

		作用域				定义位置					  语法

用户变量	当前会话				会话的任何地方			加@符号,不用指定类型
局部变量	定义它的BEGIN END中 	BEGIN END的第一句话		一般不用加@,需要指定类型

4、例子

声明两个变量并赋初值,求和,并打印

4.1、用用户变量实现

Set @m=1;
Set @n=2;
Set @sum=@m+@n;
Select @sum;

4.2、用局部变量实现

Declare m int default 1;
Declare n int default 2;
Declare sum int;
Set sum=m+n;
Select sum;

注意:一般来说这样写就好了,但是发现会报错,因为局部变量要在begin end中写,不能随便找个地方就写。

八、存储过程和函数

类似于java中的方法

好处:
1、提高了sql语句的重用性,减少了开发程序员的压力
2、提高了效率,简化操作

1、存储过程

1.1、含义

一组经过预先编译的sql语句的集合,可以理解成批处理语句

1.2、好处

1、提高了sql语句的重用性,减少了开发程序员的压力
2、简化操作
3、减少了编译次数还减少了和数据库服务器连接的次数,提高了效率。

1.3、创建存储过程

1.3.1、语法

1.3.1.1、创建语法
create procedure 存储过程名(in|out|inout 参数名  参数类型,...)
begin
	存储过程体(一组合法的sql语句)
end

类似于java的方法:
修饰符 返回类型 方法名(参数类型 参数名,…){

	方法体;
}
1.3.1.2、调用语法

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

1.3.2、注意点

1、参数列表包含三部分
参数模式 参数名 参数类型
举例:in stuname varchar(20)

参数模式:
In:这个模式可以作为输入,也就是该参数需要调用方传入值
Out:这个模式可以作为输出,也就是该参数可以作为返回值
Inout:该参数既可以作为输入又可以作为输出,既需要传入值,又可以返回值

2、如果存储过程体仅仅只有一句话,begin end 可以省略
存储过程体中的每条sql语句必须加分号。
存储过程的结尾可以用delimeter这个关键字进行重新设置结束符。

语法:
delimiter 新的结束标记
示例:
delimiter $

	CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名  参数类型,...)
	BEGIN
	sql语句1;
	sql语句2;

	END $

1.4、分类

存储过程一般都是用于增删改,而且,一般都是涉及到大量的数据,几万,几十万,甚至几百万的数据。

1.4.1、空参列表

(以admin表为例)
select * from admin
在这里插入图片描述

插入5条数据

Delimeter $
Create procedure p1()
Begin
Insert into admin(username,password) values(‘john’,0000),(‘lily’,0000),				 (‘rose’,0000),(‘jack’,0000),(‘tom’,0000)
End $

调用:
Call p1()$

在这里插入图片描述

数据已插入

1.4.2、带in模式参数的存储过程

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

Delimeter $
Create procedure p2(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 $

调用:
Call p2(‘赵敏’)$
这里面直接写跟传入的参数 beantyname类型一致的即可。

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

Delimeter $
Create procedure p3(in username varchar(20),in password varchar(20))
Begin
Declare result int default 0;   声明并初始化

Select count(*) into result    将count(*)的值赋值给自定义变量result
From admin
Where admin.username=username
And admin.password=password;

Select if(result>0,‘成功’,‘失败’);  用if语句,将结果打印在界面上
End $

调用:
Call p3(‘john’,888888)$

1.4.3、带out模式参数的存储过程

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

Delimeter $
create procedure p5(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 $

调用:
方法一:
Set @bname     //自定义一个变量,用于调用的时候放在输出值的位置
Call p5(‘赵敏’,@bname)$

方法二:也可以不自定义变量,直接使用即可
Call p5(‘赵敏’,@bname)$
Select @bname$

例子2:根据女神名,返回对应的男神名和男神魅力值(多个out可以一起使用)

Delimeter $
Create procedure p6(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 p6(‘赵敏’,@name,@usercp)$
Select @name,@usercp $

1.4.4、带inout模式参数的存储过程

例子:传入a,b两个值,最终a,b都翻倍并返回

Delimeter $
Create procedure p7(inout a int,inout b int)
Begin
Set a=a*2;
Set b=b*2;
End $

调用:
Set @m=10 $
Set @n=2 $
Call p7(@m,@n) $
Select @m,@n $

其实这里就是给a,b重新赋一下值,也就是给局部变量赋值,局部变量赋值的语法前面有说。

注意:in、out、inout都可以在一个存储过程中带多个

1.5、删除存储过程

语法:drop procedure 存储过程名;
一次只能删除一个存储过程

1.6、查看存储过程的结构

语法:Show create procedure 存储过程名;

存储过程是无法修改的,begin end里面的sql无法修改,想要改变,就只能删除存储过程重新再建立一个。

2、函数

2.1、含义

一组经过预先编译的sql语句的集合,可以理解成批处理语句

2.2、好处

1、提高了sql语句的重用性,减少了开发程序员的压力
2、简化操作
3、减少了编译次数还减少了和数据库服务器连接的次数,提高了效率。

2.3、创建函数

学过的函数:LENGTH、SUBSTR、CONCAT等
语法:

CREATE FUNCTION 函数名(参数名 参数类型,...)  RETURNS 返回类型
BEGIN
	函数体
	Return 值;
END

注意:
1、参数列表包含两部分: 参数名 参数类型
2、函数体:肯定会有return语句,如果没有会报错,如果return语句没有放在函数体的最 后也不报错,但不建议
3、函数体里面如果只有一个语句可以省略begin end
4、使用delimeter语句设置结束符

2.4、调用函数

SELECT 函数名(实参列表)

2.5、例子

2.5.1、无参有返回

返回公司的员工个数

Delimeter $
Create fuction f1() returns int
Begin
Declare c int default 0; //自定义一个变量c用于接收返回的员工个数
Select count(*)into c
From employees;
Return c;
End $

调用:
Select f1()$

2.5.2、有参有返回

例子1:根据员工名返回其工资

Delimeter $
Create function f2(empname varchar(20)) returns double
Begin
Set @sal =0;//自定义一个用户变量,也可以定义局部变量,都行
Select salary into @sal
From employees
Where last-name=empname;
Return @sal;
End $

调用:
Select f2(‘king’)$

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

Delimeter $
create function f3(deptname varchar(20))returns double
Begin
Declare sal double;
Select avg(salary) into sal
From employees e
Inner join deparments d on e.department-id=d.department-id
Where d.depatment-name=deptname;
Return sal;
End $

调用:
Select f3(‘it’)$

2.6、查看函数

Show create function 函数名;

2.7、删除函数

Drop function 函数名;

2.8、函数和存储过程的区别

		    关键字		 调用语法	    返回值			    应用场景

函数      FUNCTION	    SELECT 函数()	只能是一个		一般用于查询结果为一个值并返回时,当有								返回值而且仅仅一个

存储过程  PROCEDURE	    CALL 存储过程()	可以有0个或多个		一般用于批量插入,批量更新

2.9、流程控制结构

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

2.9.1、分支结构

2.9.1.1、if函数

实现简单的双分支
1、语法:
if(表达式1,表达式2,表达式3)
2、执行顺序:
如果表达式1成立,则返回表达式2的值,否则返回表达式3的值
3、应用:
任何地方

2.9.1.2、case语句

1、语法:

情况一:类似于java中的switch,一般用于实现等值判断

case 表达式|变量|字段
when 值1 then 结果1或语句1(如果是语句,需要加分号) 
when 值2 then 结果2或语句2(如果是语句,需要加分号)
...
else 结果n或语句n(如果是语句,需要加分号)
end 【case】(如果是放在begin end中需要加上case,如果放在select后面不需要)


情况二:类似于java中的多重if,一般用于实现区间判断
case 
when 条件1 then 结果1或语句1(如果是语句,需要加分号) 
when 条件2 then 结果2或语句2(如果是语句,需要加分号)
...
else 结果n或语句n(如果是语句,需要加分号)
end 【case】(如果是放在begin end中需要加上case,如果放在select后面不需要)

2、特点:
可以作为表达式,嵌套在其他语句中使用,可以放在任何地方;
可以作为独立的语句去使用,如果作为独立的语句使用时,只能放在begin end中。
如果when中的值或条件成立,则执行对应的then后面的语句,并且结束case;如果 都不满足,则执行else中的语句或值。
Else可以省略,如果else省略了,并且所有when条件都不满足,则返回null。

2.9.1.3、if elseif语句

实现多重分支

1、语法:

if 条件1 then 语句1;
elseif 情况2 then 语句2;
...
else 语句n;(else语句可省略)
end if;

2、特点:
只能用在begin end中!!!!!!!!!!!!!!!

2.9.2、三者比较

						应用场合
if函数				简单双分支
case结构			等值判断的多分支
if结构				区间判断的多分支

2.9.3、循环

2.9.3.1、分类

While、loop、repeat

2.9.3.2、循环控制

Iterate类似于continue,继续,结束本次循环,继续下一次
Leave 类似于break,跳出,结束当前所在的循环,没有下一次

2.9.3.3、while

1、语法:
【标签:】WHILE 循环条件 DO
循环体;
END WHILE 【标签】;

注意:写上标签,才能搭配上循环控制使用。例如有个条件是当i>=10的时候,就要跳出while循环(假设whlie循环的标签为a),在循环体里面就要进行判断,if i>=10 then leave a。

2.9.3.4、loop

1、语法:
【标签:】loop
循环体;
End loop 【标签】;

注意:这个没有循环条件,可以用来模拟死循环。

2.9.3.5、repeat

1、语法:
【标签:】repeat
循环体;
Until 结束循环的条件
End repeat【标签】;

2、例子
1、批量插入,根据次数插入到admin表中多条记录
Delimeter $
Create procedure pro1(in insertcount int)
Begin
Declare i int default 1;
While i<=insercount do
Insert into admin(username,password) values(concat(‘jonh’,i),‘666’);
Set i=i+1;
End while;
End $

Call pro1(100)$

2、添加leave,批量插入,根据次数插入到admin表中多条记录,如果次数>20则停止
Delimeter $
Create procedure pro2(in insertcount int)
Begin
Declare i int default 1;
a:while i<=insertcount do
Insert into admin(username,password)values(concat(‘xiaohua’,i), ‘0000’);
If i>=20 then leave a;
End if;
Set i=i+1;
End while a;
End $

Call pro2(100)$

虽然我们传入的值是100,但是当次数到达20的时候,就会停止插入。
在这里插入图片描述

3、添加iterate,批量插入,根据次数插入到admin表中多条记录,只插入偶数次
Delimeter $
Create procedure pro2(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(‘xiaohua’,i), ‘0000’);
End while a;
End $

Call pro2(100)$

2.9.3.6、三者之间的比较

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_42389904/article/details/114375093
今日推荐