目录

一、为什么要学习数据库

二、数据库的相关概念

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

四、初始MySQL

MySQL产品的介绍和安装

MySQL服务的启动和停止

MySQL服务的登录和退出

MySQL的常见命令

MySQL的语法规范

*SQL的语言分类

五、DQL语言(数据查询语言)

进阶1:基础查询

进阶2:条件查询

进阶3:排序查询

进阶4:常见函数

进阶5:分组查询

进阶6:连接查询/多表查询/多表连接查询

进阶7:子查询

进阶8:分页查询

进阶9:联合查询

六、DML语言(数据操作语言)

插入语句

修改语句

删除语句

七、DDL语言(数据定义语言)

库和表的管理

库的管理:

表的管理:

常见的数据类型

一、数值型中的整型

二、数值型中的小数

三、字符型

四、日期型(必须用单引号引起来)

常见约束

标识列:又称为自增长列

八、TCL语言(事务控制语言)

*存储引擎(表类型):

事务:

事务的ACID属性:【面试题】

事务的分类:

事务的隔离级别:

事务并发问题的发生:

事务的并发问题:

数据库事务的隔离性:

隔离级别:

数据库提供的4种事务隔离级别:

Oracle、Mysql支持的事务隔离级别和默认的事务隔离级别:

4种事务隔离级别案例演示:

演示savepoint 的使用:

演示事务对于delete和truncate的处理的区别:

九、视图

十、变量

十一、存储过程和函数

存储过程

函数

函数和存储过程的区别

十二、流程控制结构

顺序结构

分支结构

循环结构


一、为什么要学习数据库

数据库的好处

1.持久化数据到本地

2.可以实现结构化查询,方便管理

二、数据库的相关概念

数据库相关概念

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

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

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

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

数据库存储数据的特点

1.将数据放到表中,表再放到库中

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

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

4.表由列组成,我们也称为字段。所有表都是由一个或多个列组成的,每一列类似java 中的“属性”。

5.表中的数据是按行存储的,每一行类似于java中的“对象”。

常见的DBMS:MySQL、Oracle、DB2、SqlServer

Oracle:贵

DB2:适合处理大量数据

SqlServer:只能安装在windows操作系统下

DBMS分为两类:

–基于共享文件系统的DBMS,如Access

–基于客户机——服务器的DBMS,如MySQL、Oracle、SqlServer

客户机服务器,简称C/S架构,C代表客户端,S代表服务端。

MySQL使用时需要安装客户端和服务端。

“安装数据库”一般指安装数据库的服务端。

四、初始MySQL

MySQL产品的介绍和安装

MySQL服务的启动和停止

方式一:计算机——右击管理——服务(Windows管理工具——服务)

方式二:通过管理员身份运行(cmd——以管理员身份运行)

net start 服务名(启动服务)(net start mysql)

net stop 服务名(停止服务)(net stop mysql)

MySQL服务的登录和退出

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

方式二:通过windows自带的客户端

登录:mysql -uroot -p123456

mysql 【-h主机名 -P端口号 】-u用户名 -p密码(对于连接本机的端口号为3306的登录,【】中内容可以省略)

若显示密码:mysql -h localhost -P 3306 -u root -p123456

(注意:hlocalhost、P3306、uroot之间有无空格都可,但是p123456之间不能有空格,其中123456是账号root的密码)

若不想显示密码:mysql -h localhost -P 3306 -u root -p 按下回车键,再输入密码。

退出:exit或快捷键ctrl+c(此方式只适合root用户)

MySQL的常见命令

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

共4个数据库,其中:

information_schema用于保存元数据信息

mysql用于保存用户信息

performance_schema搜集性能信息、性能参数

sys

前3个不能动

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

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

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

use sys;

show tables;

show tables from mysql;#在sys库中查看mysql库中所有的表

select database();#查看目前在哪个库,不要忘记()

5.创建表:

create table 表名(

列名 列类型,

列名 列类型,

…#最后一个字段不用加,

);

6.查看表结构,查看、插入、修改、删除表数据

查看表结构:desc 表名;

查看表数据:select * from 表名;

插入表数据:insert into 表名 (id,name) values(1,'john');

修改表数据:update 表名 set name='rose' where id=1;

删除表数据:delete from 表名 where id=1;

7.查看服务器的版本

方式一:登录到mysql服务端:select version();

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

MySQL的语法规范

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

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

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

4.注释

单行注释:#注释文字

单行注释:-- 注释文字#注意--与文字之间有空格

多行注释:/* 注释文字  */

*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

执行sql脚本myemployees.sql,手动刷新。

五、DQL语言(数据查询语言)

进阶1:基础查询

语法:

SELECT 查询列表    #要查询的东西可以有多个
【FROM 表名】;

特点:

通过select查询完的结果,是一个虚拟的表格,不是真实存在的;

查询列表可以是:表中的字段、常量值、表达式、字段、函数

补充:

在做查询或一些操作之前,建议先打开/启用指定的库:use myemployees;

着重号`用以区分字段和关键字(键盘左上角第2排第1个)

要执行谁就选中谁,点击“执行查询”或者F9

不区分“字符”和“字符串”,没有“字符串”的概念,只要是字符,都用’’

commission_pct(奖金率)字段中有null,因此利用ifnull函数:

ifnull (字段名,如果该字段为null想要返回的值)

进阶2:条件查询

条件查询:

根据条件过滤原始表的数据,查询到想要的数据

语法:

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

分类:

一、按条件表达式筛选

简单条件运算符: >  <  >=  <=  =  !=  <>(mysql中标准写法为<>,也支持!=)

案例1:查询工资大于12000员工信息

select *
from employees
where salary>12000;

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

select last_name,department_id
from employees
where department_id <>90;

二、按逻辑表达式筛选

逻辑运算符:

and(&&):两个条件同时成立,结果为true,否则为false

or(||):两个条件只要有一个成立,结果为true,否则为false

not(!):如果条件成立,则not后为false,否则为true

案例1:查询工资在10000到20000之间的员工名、工资和奖金

select last_name,salary,commission_pct
from employees
where salary>10000 and salary<20000;

案例2:查询部门编号不是在90到110之间,或者工资高于15000的员工信息

select * from employees
where department_id<90 or department_id>110 or salary>15000;
select * from employees
where not (department_id>=90 and department_id<=110) or salary>15000;

三、模糊查询

符号(较为复杂的条件运算符):

(一)like

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

通配符:

①%:任意多个字符,包含0个字符

案例1:查询员工名中包含字符a的员工信息(字符型的值必须用''引起来)

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

②_:任意单个字符

案例2:查询员工名中第三个字符为e,第五个字符为a的员工信息

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

案例3:查询员工名中第二个字符为_的员工信息

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

可随意指定转义字符,但要同时使用escape

SELECT * FROM employees WHERE last_name LIKE '_$_%' ESCAPE '$';

(二)between and

①提高语句的简洁度

②包含临界值

③两个临界值不要调换顺序

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

SELECT * FROM employees WHERE employee_id >= 120 AND employee_id<=100;
SELECT * FROM employees WHERE employee_id BETWEEN 120 AND 100;

(三)in

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

特点:

①提高语句简洁度

②in列表的值类型必须一致或兼容

③in列表中不支持通配符

案例:查询工种编号是IT_PROG、AD_VP之一的员工名和工种编号

SELECT last_name,job_id FROM employees WHERE job_id = 'IT_PROT' OR job_id = 'AD_VP';
SELECT last_name,job_id FROM employees WHERE job_id IN( 'IT_PROT' ,'AD_VP');

(四)is null/is not null

=或<>不能用于判断null值,而is null或is not null可以判断null值

案例1:查询没有奖金的员工名

SELECT last_name FROM employees WHERE commission_pct IS NULL;

案例1’:查询有奖金的员工名

SELECT last_name FROM employees WHERE commission_pct IS NOT NULL;

安全等于<=>(判断是否等于null值,也可以判断是否等于普通类型的值,可读性较差)

案例1’’:查询没有奖金的员工名

SELECT last_name FROM employees WHERE commission_pct <=> NULL;

案例2:查询工资为12000的员工信息

SELECT last_name,salary FROM employees WHERE salary <=> 12000;

is null和<=>比较:

IS NULL:仅仅可以判断NULL值,可读性较高,建议使用

<=>:既可以判断NULL值,又可以判断普通的数值,可读性较低

进阶3:排序查询

语法:

select 查询列表
from 表名
where 筛选条件
order by 排序列表 【asc|desc】

特点:

asc代表升序,不写默认升序,desc代表降序

order by子句可以支持 单个字段、别名、表达式、函数、多个字段

order by子句在查询语句的最后面(除了limit子句)

案例:

1.按单个字段排序

SELECT *
FROM employees
ORDER BY salary DESC;

2.添加筛选条件再排序

案例:查询部门编号>=90的员工信息,并按员工编号降序

SELECT *
FROM employees
WHERE department_id>=90
ORDER BY employee_id DESC;

3.按表达式排序

案例:查询员工信息,按年薪降序

SELECT *,salary*12*(1+IFNULL(commission_pct,0)) 年薪
FROM employees
ORDER BY salary*12*(1+IFNULL(commission_pct,0)) DESC;

4.按别名排序

案例:查询员工信息,按年薪升序

SELECT *,salary*12*(1+IFNULL(commission_pct,0)) 年薪
FROM employees
ORDER BY 年薪 ASC;

5.按函数排序

案例:查询员工名,并且按名字的长度降序

SELECT last_name
FROM employees
ORDER BY LENGTH(last_name) DESC;

6.按多个字段排序

案例:查询员工信息,要求先按工资降序,再按employee_id升序

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

进阶4:常见函数

概念:

类似于java的方法,将一组逻辑语句封装在方法体中,对外暴露方法名

好处:

隐藏了实现细节

提高代码的重用性

调用:

select 函数名(实参列表)
【from 表名】;

函数中参数用到表中字段需要加【from表名】,没用到就不用加

特点:

①叫什么(函数名)

②干什么(函数功能)

一、单行函数:做处理使用,传进一个值,返回一个值

(一)字符函数

1.length获取字节个数

SELECT LENGTH('张三丰hahaha');

SHOW VARIABLES LIKE '%char%'

显示字符集,utf8中1个汉字占3个字符, gdk中1个汉字占2个字符

2.concat拼接字符串

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

3.upper转换成大写,lower转换成小写

示例:将姓变大写,名变小写,然后拼接

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

4.substr/substring截取字符(注意:索引从1开始)

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

SELECT SUBSTR('李莫愁爱上了陆展元',7) out_put;

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

SELECT SUBSTR('李莫愁爱上了陆展元',1,3) out_put; 

其中,3表示截取长度

案例3:姓名中首字符大写,其他字符小写然后用_拼接,显示出来(视频中“姓名”指“姓”)

select concat(
upper(substr(concat(last_name,first_name),1,1)),
'-',
lower(substr(concat(last_name,first_name),2)))
from employees;

5.instr返回子串第一次出现的索引(找不到返回0)

6.trim去前后空格和指定的字符

SELECT TRIM('a' FROM 'aaaaaaaaa张a翠山aaaaaaaaaaaaaaaaaa')  AS out_put;

结果:张a翠山

7.ltrim去左边空格,rtrim去右边空格

8.lpad用指定的长度实现左填充,rpad用指定的长度实现右填充

SELECT LPAD('殷素素',10,'*') AS out_put;

结果的总字符个数为10

SELECT LPAD('殷素素',2,'*') AS out_put; 

结果:殷素

9.replace替换(都会替换)

SELECT REPLACE('周芷若张无忌爱上了周芷若','周芷若','赵敏'); 

(二)数学函数

1.round 四舍五入

SELECT ROUND(1.567,2);

结果保留2位小数

2.ceil向上取整,返回大于等于该参数的最小整数

3.floor向下取整,返回小于等于该参数的最大整数

4.truncate截断

SELECT TRUNCATE(1.69999,1); 

结果保留1位小数,1.6

5.mod取余(mod(a,b)=a-a/b*b,结果的正负与被除数保持一致)

6.rand 随机数,返回0到1之间的小数

(三)日期函数

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

2.curdate当前系统日期(cur指current)

3.curtime当前系统时间

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

SELECT YEAR(NOW()) 年;
SELECT MONTH(NOW()) 月;
SELECT MONTHNAME(NOW()) 月; 

以英文形式返回月

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

SELECT *
FROM employees
WHERE hiredate = STR_TO_DATE('4-3 1992','%c-%d %Y');

6.date_format将日期转换成字符

SELECT DATE_FORMAT('2021/9/14','%Y年%m月%d日');

结果:2021年09月14日

7.datediff函数返回两个日期相差的天数

案例:查询员工表中的最大入职时间和最小入职时间的相差天数(difference)

SELECT DATEDIFF(MAX(hiredate),MIN(hiredate)) diffrence
FROM employees;

(四)其他函数

1.version当前数据库服务器的版本

2.database当前打开的数据库

3.user当前连接用户

4.password(‘字符’)返回该字符的密码形式,即自动加密

5.md5(‘字符’)返回该字符md5加密形式

(五)流程控制函数

1.if函数:if else 的效果

SELECT IF(10<5,'大','小');
SELECT last_name,IF(commission_pct IS NULL,'无','有') FROM employees;

2.case函数

使用一:switch case的效果(处理等值判断)

case 要判断的字段或表达式
when 常量1 then 要显示的值1或语句1; (若为值,不用加;)
when 常量2 then 要显示的值2或语句2;
...
else 要显示的值n或语句n;
end

使用二:类似于多重if(处理条件判断)

case
when 条件1 then 要显示的值1或语句1
when 条件2 then 要显示的值2或语句2
...
else 要显示的值n或语句n
end

二、分组函数/统计函数/聚合函数/组函数:做统计使用,传进一组值,返回一个值

sum求和

max最大值

min最小值

avg平均值

count计数

特点:

1.sum和avg一般用于处理数值型,max、min、count可以处理任何数据类型

2.以上五个分组函数都忽略null值,null值并未参与运算,除了count(*)

3.都可以搭配distinct使用,用于统计去重后的结果(distinct 字段)

4.count的参数可以支持:

(1)字段

(2)*(结果是总行数)

(3)常量值,一般放1(假设加了一列,该列每个格子中都是1,结果是总行数)

效率:

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

INNODB存储引擎下,COUNT(*)和COUNT(1)的效率差不多,比COUNT(字段)要高一些,因为COUNT(字段)需要先判断该字段的值是否为null,有筛选过程。

建议使用COUNT(*)

5.和分组函数一同查询的字段要求是group by后的字段

进阶5:分组查询

语法:

select分组函数,列〈要求出现在group by的后面〉
from表
【where 筛选条件】
group by 分组的列表
【having 分组后的筛选】
【order by 子句】

执行顺序:

from->where->group by->having->select->order by

order by除limit语句之外放在最后

order by支持别名,经验证group by和having也支持别名,但少用

特点:

1.和分组函数一同查询的字段必须是group by后出现的字段

2.【面试题】

筛选分类

数据源

位置

连接的关键字

分组前筛选

原始表

group by前

where

分组后筛选

分组后的结果集

group by后

having

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

能用分组前筛选的,优先考虑使用分组前筛选,提高效率

3.group by子句支持:

单个字段分组

多个字段分组(,隔开,无先后顺序)

表达式或函数(使用较少)

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

案例:

简单分组(“每个”后面是分组标准)

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

select max(salary),job_id
from employees
group by job_id;

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

select count(*),location_id
from departments
group by location_id;

添加筛选条件(分组前筛选)

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

select max(salary),department_id
from employees
where email like '%a%'
group by department_id;

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

select avg(salary),manager_id
from employees
where commission_pct is not null
group by manager_id;

添加复杂的筛选条件(分组后筛选)

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

select count(*),department_id
from employees
#where count(*)>2    #员工表中没有count(*)字段,报错!!!
group by department_id
having count(*)>2;    #正确做法

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

select job_id,max(salary)
from employees
where commission_pct is not null
group by job_id
having max(salary)>12000;

案例3:领导编号>102的每个领导手下最低工资>5000的领导编号和最低工资

select manager_id,min(salary)
from employees
where manager_id>102
group by manager_id
having min(salary)>5000;

按表达式或函数分组

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

select length(last_name),count(*)
from employees
group by length(last_name)    #group by后面也支持函数/表达式/别名
having count(*)>5;    #group by和having后面支持别名,但不常用,但是where后面不支持别名

按多个字段进行分组

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

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;

进阶6:连接查询/多表查询/多表连接查询

含义:

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

笛卡尔乘积现象:

表1 有m行,表2有n行,结果=m*n行

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

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

分类:

按年代分类:

sql92标准:仅仅支持内连接

sql99标准【推荐】:支持内连接+外连接(左外和右外)+交叉连接

按功能分类:

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

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

交叉连接

一、sql92标准

(一)等值连接

①多表等值连接的结果为多表的交集部分

②n表连接,至少需要n-1个连接条件

③多表的顺序没有要求

④一般需要为表起别名

⑤可以搭配前面介绍的所有子句使用,比如排序、分组、筛选

1.简单的连接

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

SELECT last_name,department_name
FROM employees,departments
WHERE employees.department_id=departments.department_id;

2.为表起别名(提高语句简洁度,区分多个重名字段)

注意:如果为表起了别名,则查询的字段就不能使用原来的表名去限定

案例:查询员工名、工种号、工种名

SELECT e.last_name,j.job_id,j.job_title
FROM employees e,jobs j
WHERE e.job_id=j.job_id;

3.两个表的顺序可以调换

4.可以加筛选

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

select last_name,department_name
from employees e,departments d
where e.department_id=d.department_id
and 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%';

5.可以加分组

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

select city,count(*) 部门个数
from locations l,departments d
where l.location_id=d.location_id
group by city;

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

select department_name,d.manager_id,min(salary)
from departments d,employees e
where d.department_id=e.department_id
and commission_pct is not null
group by department_name,manager_id;    #不能确定这两个字段一一对应,因此分组条件都写上

6.可以加排序

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

select job_title,count(*)
from jobs j,employees e
where j.job_id=e.job_id
group by job_title
order by count(*) desc;

7.可以三表连接

(二)非等值连接

案例1:查询员工的工资和工资级别(excel中模糊比对)

SELECT salary,grade_level
FROM employees e,job_grades g
WHERE salary BETWEEN g.`lowest_sal` AND g.`highest_sal`;

(三)自连接

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

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

二、sql99语法:通过join关键字实现连接

含义:

1999年推出的sql语法

支持:

支持内连接+外连接(左外和右外)+交叉连接

语法:

select 查询列表
from 表1 别名
【连接类型】 join 表2    #原来的,替换成【连接类型】 join
on 连接条件                #原来的连接条件用where,替换成on
【连接类型】 join 表3
on 连接条件
【where 筛选条件】
【group by 分组字段】
【having 分组后的筛选条件】
【order by 排序的字段或表达式】

连接类型:

内连接inner

外连接

左外left【outer】

右外right【outer】

全外full【outer】 mysql不支持全外

交叉连接cross

好处:

语句上,连接条件(on)和筛选条件(where)实现了分离,简洁明了。

(一)内连接(等值连接、非等值连接、自连接)

特点:

①添加排序、分组、筛选

②inner可以省略

③ 筛选条件放在where后,连接条件放在on后,提高分离性,便于阅读

④inner join连接和sql92语法中的等值连接效果一样,都是查询多表的交集

1.等值连接

案例:查询部门个数>3的城市名和部门个数

select city,count(*)
from locations l
inner join departments d
on l.location_id=d.location_id
group by city
having count(*)>3;

2.非等值连接

案例:查询工资级别中员工个数>20的并且按工资级别降序排列

select count(*),grade_level
from employees e
inner 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;

3.自连接

案例:查询姓名中包含字符k的员工及其上级的名字

select e.last_name,m.last_name
from employees e
inner join employees m
on e.manager_id=m.employee_id
where e.last_name like ‘%k%’;

(二)外连接(左外、右外、全外)

应用场景:

用于查询一个表中有,另一个表没有的记录

特点:

1.外连接的查询结果为主表中的所有记录

如果从表中有和它匹配的(连接条件一致),则显示匹配的值

如果从表中没有和它匹配的,则显示null

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

2.左外连接,left 【outer】 join左边的是主表

右外连接,right 【outer】 join右边的是主表

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

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

5.全外连接(mysql不支持)

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

主表:看想查询的内容来自于哪个表,该例中主表为女神表

select b.name,
from beauty b
left outer join boys bo     #或from boys bo right outer join beauty b
on b.boyfriend_id=bo.id
where bo.id is null;        #最好选择从表中的主键列

案例:查询哪个部门没有员工(部门表为主表)

select department_name
from departments d
left join employees e
on d.department_id=e.department_id
where employee_id is null;        #去掉内连接结果,剩下非交集部分

(三)交叉连接

笛卡尔乘积

sql92和 sql99pk

功能:sql99支持的较多

可读性:sql99实现连接条件和筛选条件的分离,可读性较高

进阶7:子查询

含义:

一条查询语句中又嵌套了另一条完整的select语句,其中被嵌套的select语句,称为子查询或内查询;

在外面的查询语句,称为主查询或外查询。

分类:

按子查询出现的位置:

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

from后面:支持表子查询

where或having后面:

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

列子查询(多行子查询)

行子查询(用的较少)

exists后面(相关子查询)

表子查询

按结果集的行列数不同:

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

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

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

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

特点:

①子查询放在小括号内

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

③标量子查询,一般搭配着单行操作符使用>  <  >=  <=  =  <>

列子查询,一般搭配着多行操作符使用in  any/some  all

④子查询的执行优先于主查询执行,主查询的条件用到了子查询的结果

一、where或having后面:

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

案例1:查询工资比Abel高的员工信息

select *
from employees
where salary>(select salary from employees where last_name=’Abel’);

案例2:返回工种编号与141号员工(的工种编号)相同,工资比143号员工(的工资)多的员工姓名,job_id 和工资

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 last_name,job_id,salary
from employees
where salary=(select min(salary) from employees);

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

select department_id,min(salary)
from employees
group by (department_id)
having min(salary)>(select min(salary) from employees where department_id=50);

非法使用标量子查询(子查询的结果集不是一行一列)

SELECT MIN(salary),department_id
FROM employees
GROUP BY department_id
HAVING MIN(salary)>(SELECT salary FROM employees WHERE department_id=250);

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

多行操作符:

in/not in等于列表中的任意一个

判断a是否in(1,2,3),a=1或2或3,都可显示。括号内替换成查询语句。

any|some和子查询返回的某一个值比较

a>any(1,2,3)等价于a>min(1,2,3)

all 和子查询返回的所有值比较*

a>all(1,2,3)等价于a>max(1,2,3)

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

select last_name from employees
where department_id in(
select distinct department_id from departments where location_id in(1400,1700));

案例2:返回其它工种中比job_id为‘IT_PROG’工种任一工资低的员工的员工号、姓名、job_id以及salary

select employee_id,last_name,job_id,salary
from employees
where salary<any (select distinct salary from employees where job_id=’IT_PROG’)
and job_id<>’IT_PROG’;

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);

二、select后面:仅仅支持标量子查询

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

select d.*,(
select count(*)
from employees e
where e.department_id=d.department_id
)
from departments d;

三、from后面:将子查询的结果集充当表格使用,几行几列都可以,必须起别名。

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

1’查询每个部门的平均工资

select avg(salary),department_id from employees group by department_id

2’连接1’的结果集和工资等级表,非等值连接

select ag_dep.*,g.grade_level
from job_grades g
inner join(select avg(salary) ag,department_idfrom employeesgroup by department_id
) ag_dep
on ag_dep.ag between lowest_sal and highest_sal;

四、exists后面(相关子查询):只关心子查询的结果有没有值。结果是布尔类型。

语法:

exists(完整的查询语句)

结果:1或0

执行顺序:先执行外查询,再根据子查询过滤。

案例1:查询有员工的部门名

用exists:

select department_name
from departments d
where exists(select * from employees e where d.department_id=e.department_id);

用in:

select department_name
from departments d
where d.department_id in(select department_id from employees);

案例2:查询没有女朋友的男神信息

用exists:

select bo.*
from boys bo
where not exists(
select boyfriend_id from beauty b where bo.id=b.boyfriend_id);

用in:

select bo.*
from boys bo
where bo.id not in (select boyfriend_id from beauty);

进阶8:分页查询

应用场景:

当要显示的数据,一页显示不全,需要分页提交sql请求

语法:

                            #执行顺序
select 查询列表                #7
from 表                        #1
【join type join 表2           #2
on 连接条件                    #3
where 筛选条件                 #4
group by 分组字段              #5
having 分组后的筛选             #6
order by 排序的字段】           #8
limit 【offset,】size;          #9

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

size要显示的条目个数

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

select *
from employees
limit 0,5;

或(从第一条开始可以忽略起始索引)

select *
from employees
limit 5; 

案例2:查询第11条到第25条员工信息

select *
from employees
limit 10,15;

案例3:显示有奖金且工资较高的前十名的员工信息

select *
from employees
where commisstion_pct is not null
order by salary desc
limit 10;

特点:

①limit语句放在查询语句的最后,语法上在最后,执行顺序也是最后。

②公式

要显示的页数page,每页的条目数size

select 查询列表
from 表
limit (page-1)*size,size;

找规律:

每页条目数size=10

要显示的页数page=1:第1页—>起始索引0

要显示的页数page=2:第2页—>起始索引10

要显示的页数page=3:第3页—>起始索引20

进阶9:联合查询

union(联合/合并):

将多条查询语句的结果合并成一个结果

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

法一:

select *
from employees
where department_id>90
or email like '%a%';

法二:

select * from employees where department_id>90
union
select * from employees where email like '%a%';

语法:

查询语句1
union
查询语句2
union
...

应用场景:

要查询的结果来自多个表,且多个表没有直接的连接关系,但查询信息一致

特点:

1.多条查询语句的查询列数必须一致

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

3.union关键字默认去重,如果使用union all 可以包含重复项

六、DML语言(数据操作语言)

插入:insert

修改:update

删除:delete

插入语句

方式一:经典的插入

语法:

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

特点:

1.插入的值的类型要与列的类型一致或兼容,且一一对应

INSERT INTO beauty(id,NAME,sex,borndate,phone,photo,boyfriend_id)
VALUES(13,'唐艺昕','女','1990-4-23','1898888888',NULL,2);

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

方式一:列名写上,值用null填充

INSERT INTO beauty(id,NAME,sex,borndate,phone,photo,boyfriend_id)
VALUES(13,'唐艺昕','女','1990-4-23','1898888888',NULL,2);

方式二:列名和值都不写

INSERT INTO beauty(id,NAME,sex,phone)
VALUES(15,'娜扎','女','1388888888');

3.列的顺序是否可以调换

INSERT INTO beauty(NAME,sex,id,phone)
VALUES('蒋欣','女',16,'110');

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

INSERT INTO beauty(NAME,sex,id,phone)
VALUES('关晓彤','女',17,'110');

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

INSERT INTO beauty
VALUES(18,'张飞','男',NULL,'119',NULL,NULL);

方式二:

语法:

insert into 表名
set 列名=值,列名=值,...
INSERT INTO beauty
SET id=19,NAME='刘涛',phone='999';

两种方式大pk

1.方式一支持插入多行,方式二不支持

INSERT INTO beauty
VALUES(23,'唐艺昕1','女','1990-4-23','1898888888',NULL,2),
(24,'唐艺昕2','女','1990-4-23','1898888888',NULL,2),
(25,'唐艺昕3','女','1990-4-23','1898888888',NULL,2);

2.方式一支持子查询,方式二不支持

INSERT INTO beauty(id,NAME,phone)
SELECT 26,'宋茜','11809866';
INSERT INTO beauty(id,NAME,phone)
SELECT id,boyname,'1234567'
FROM boys
WHERE id<3;

修改语句

修改单表语法:

update 表名
set 列=新值,列=新值,...
【where 条件】    #不加where所有行都更新

执行顺序:

update->where->set

案例1:修改beauty表中姓唐的女神的电话为13899888899

update beauty
set phone='13899888899'
where name like '唐%';

案例2:修改boys表中id好为2的名称为张飞,魅力值为10

update boys
set boyname='张飞',usercp=10
where id=2;

修改多表语法:(级联更新)

sql92语法:

update 表1 别名,表2 别名
set 列=值,...
where 连接条件
and 筛选条件;      

sql99语法:

update 表1 别名
inner|left|right join 表2 别名
on 连接条件
set 列=值,...
where 筛选条件;

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

sql92:

update beauty b,boys bo
set b.phone='114'
where b.boyfriend_id=bo.id
and bo.boyname='张无忌';

sql99:

update beauty b
inner join boys bo
on b.boyfriend_id=bo.id
set b.phone='114'
where bo.boyname='张无忌';

案例2:修改没有男朋友的女神的男朋友编号都为2号(外连接,beauty表为主表)

sql92:

update beauty b,boys bo
set b.boyfriend_id=2
where b.boyfriend_id=bo.id
and b.boyfriend_id is null;

sql99:

update beauty b
left join boys bo
on b.boyfriend_id=bo.id
set b.boyfriend_id=2
where b.boyfriend_id is null    #或bo.id is null (b.boyfriend_id=bo.id)

删除语句

方式一:delete语句(删除部分行的记录)

语法:

单表的删除:

delete from 表名
【where 筛选条件】

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

delete from beauty
where phone like '%9';

多表的删除:

sql92语法:

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

sql99语法:

delete 表1的别名,表2的别名
from 表1 别名
inner|left|right join 表2 别名
on 连接条件
where 筛选条件;

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

sql92:

delete b    #仅删除女神表中的信息,delete后只写beauty表的别名b
from beauty b,boys bo
where b.boyfriend_id=bo.id
and bo.boyname='张无忌';

sql99:

delete b
from beauty b
inner join boys bo
on b.boyfriend_id=bo.id
where bo.boyname='张无忌';

案例2:删除黄晓明的信息以及他女朋友的信息(删除两个表中的信息,级联删除)

sql99:

delete b,bo
from beauty b
inner join boys bo
on b.boyfriend_id=bo.id
where bo.boyname='黄晓明';

方式二:truncate语句(删除整个表的数据)

语法:

truncate table 表名

案例:将魅力值>100的男神信息删除(不允许加where!!!)

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

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

2.truncate删除,效率高一丢丢

3.假如要删除的表中有自增长列,如果用delete删除后,再插入数据,自增长列的值从断点开始,而truncate删除后,再插入数据,自增长列的值从1开始。

4.truncate删除没有返回值(共0行受到影响,不写明删除了几行),delete删除有返回值(确切写明共几行删除)

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

七、DDL语言(数据定义语言)

库和表的管理

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

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

创建: create

修改: alter

删除: drop

库的管理:

1.创建库:

create database 【if not exists】 库名
create database if not exists books;    #提高容错性,若无库则建库,有库则不报错

2.修改库:

一般不修改,不稳定。

若要修改库中的表,则直接更改表的操作;

若要修改库名,则找到相关文件夹手动修改;

可以更改库的字符集:(右击数据库名,点击“改变数据库”可查看“基字符集”)

alter database books character set utf8;

3.删除库:

drop database 【if exists】 库名

表的管理:

1.表的创建

语法:

create table 表名(列名 列的类型【(长度) 约束】,列名 列的类型【(长度) 约束】,...列名 列的类型【(长度) 约束】
);

案例1:创建表Book

CREATE TABLE book(id INT,bName VARCHAR(20),price DOUBLE,authorId  INT,publishDate DATETIME
);

查看book表的结构:

DESC book;

案例2:创建表author

CREATE TABLE IF NOT EXISTS author(id INT,au_name VARCHAR(20),nation VARCHAR(10)
);

2.表的修改

语法:

alter table 表名 change|modify|add|drop column 列名 【列类型 约束】;

①修改列名(column可以省略;最后一定要加上列类型,同时可以修改类型)

ALTER TABLE book CHANGE COLUMN publishdate pubDate DATETIME;

②修改列的类型或约束

ALTER TABLE book MODIFY COLUMN pubdate TIMESTAMP;

③添加新列

ALTER TABLE author ADD COLUMN annual DOUBLE;

④删除列(不需要加列类型)

ALTER TABLE book_author DROP COLUMN annual;

⑤修改表名

ALTER TABLE author RENAME TO book_author;

3.表的删除

语法:

drop table if exists 表名;

查看当前库的所有表:

show tables;

❤通用的写法:

DROP DATABASE IF EXISTS 旧库名;
CREATE DATABASE 新库名;
DROP TABLE IF EXISTS 旧表名;
CREATE TABLE 新表名();

4.表的复制

语法:

①仅仅复制表的结构

create table 新表名 like 旧表名;

②复制表的结构和数据

create table 新表名
select * from 旧表名;

③只复制部分数据

create table 新表名
select 某些字段名
from 旧表名
where 筛选条件;

④仅仅复制部分结构(某些字段)

create table 新表名
select 某些字段名
from 旧表名 where 0;    #或where恒不成立的筛选条件

案例讲解(可以跨库):

将表departments(存在于myemployees库)中的数据插入新表dept2(需创建在test库)中

create table dept2
select department_id,department_name
from myemployees.departments;

常见的数据类型

数值型:

整型

小数:

定点数

浮点数

字符型:

较短的文本:char、varchar

较长的文本:text、blob(较长的二进制数据,如图片)

日期型

一、数值型中的整型

分类:

整数类型 tinyint smallint mediumint int/integer bigint
字节 1 2 3 4 8

特点:

①如果不设置无符号还是有符号,默认有符号;如果想设置无符号,需要添加unsigned关键字

问题:如何设置无符号和有符号

DROP TABLE IF EXISTS tab_int;
CREATE TABLE tab_int(t1 INT,t2 INT UNSIGNED
);
DESC tab_int;

检验:

INSERT INTO tab_int VALUES(-123456,-123456);
SELECT * FROM tab_int;
#查看tab_int表中的内容,结果:t1显示的值为-123456,t2显示的值为0(即临界值)

② 如果插入的数值超出了整型的范围,会报out of range异常,并且插入临界值

检验:

INSERT INTO tab_int VALUES(2147483648,4294967296);
SELECT * FROM tab_int;
#查看tab_int表中的内容,结果:t1显示的值为2147483647,t2显示的值为4294967295(均为临界值)

③ 如果不设置长度,会有默认的长度;

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

范围是由类型决定的,而不是由长度决定

检验(未搭配zerofill):

CREATE TABLE tab_int(t1 INT(7),t2 INT(7)
);
INSERT INTO tab_int VALUES(123,123);
SELECT * FROM tab_int;
#结果:123 123

检验(搭配zerofill):

CREATE TABLE tab_int(t1 INT(7) ZEROFILL,t2 INT(7) ZEROFILL
);
INSERT INTO tab_int VALUES(123,123);
SELECT * FROM tab_int;
#结果:0000123 0000123

检验(只要一加上zerofill,int的范围默认变成无符号):

INSERT INTO tab_int VALUES(-123456,-123456);
SELECT * FROM tab_int;
#结果:0000000 0000000

二、数值型中的小数

分类:

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

定点型:decimal(M,D)或简写为dec(M,D)

特点:

①M:整数部位+小数部位,D:小数部位

如果超过范围,则插入临界值

②M和D都可以省略

如果是decimal类型,则M默认为10,D默认为0

如果是float或double类型,则会根据插入的数值的精度来决定M和D的值

③定点型的精确度较高,如果要求插入数值的精度较高,如货币运算等则考虑使用

测试M和D:

DROP TABLE tab_float;
CREATE TABLE tab_float(f1 FLOAT(5,2),f2 DOUBLE(5,2),f3 DECIMAL(5,2)
);
SELECT * FROM tab_float;
DESC tab_float;
INSERT INTO tab_float VALUES(123.45,123.45,123.45);
#结果:123.45 123.45 123.45
INSERT INTO tab_float VALUES(123.456,123.456,123.456);
#结果:123.46 123.46 123.46
INSERT INTO tab_float VALUES(123.4,123.4,123.4);
#结果:123.40 123.40 123.40
INSERT INTO tab_float VALUES(1523.4,1523.4,1523.4);
#结果:999.99 999.99 999.99

原则:

所选择的类型越简单越好,能保存数值的类型越小越好(节省空间)

三、字符型

较短的文本:

char

varchar

说明:用来保存mysql中较短的字符串

注意:M表示最多字符数,一个a是一个字符,一个汉字也是一个字符

区别:char代表固定长度的字符,varchar代表可变长度的字符

特点:

写法

M的意思

特点

空间耗费

效率

char

char(M)

最大字符数,

可省略,默认为1

固定长度的字符

比较耗费

varchar

varchar(M)

最大字符数,

不可省略

可变长度的字符

比较节省

较长的文本:

text

blob(较大的二进制)

其他:

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

enum用于保存枚举:

CREATE TABLE tab_char(c1 ENUM('a','b','c'));
INSERT INTO tab_char VALUES('m');    #不能成功插入
INSERT INTO tab_char VALUES('A');    #可以成功插入

set用于保存集合:CREATE TABLE tab_set(s1 SET('a','b','c','d'));

INSERT INTO tab_set VALUES('a');
INSERT INTO tab_set VALUES('A,B');
INSERT INTO tab_set VALUES('a,c,d');
SELECT * FROM tab_set;

四、日期型(必须用单引号引起来)

分类:

date保存日期

time 只保存时间

year只保存年

datetime保存日期+时间

timestamp保存日期+时间

特点:

字节

范围

时区等的影响

datatime

8

1000—9999

不受

timestamp

4

1970—2038

CREATE TABLE tab_date(t1 DATETIME,t2 TIMESTAMP
);INSERT INTO tab_date VALUES(NOW(),NOW());
SELECT * FROM tab_date;
SHOW VARIABLES LIKE 'time_zone';
SET time_zone='+9:00';

常见约束

含义:

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

语法:

CREATE TABLE 表名(字段名 字段类型 列级约束,字段名 字段类型,表级约束
);

分类:六大约束

NOT NULL:非空,用于保证该字段的值不能为空。比如姓名、学号等

DEFAULT:默认,用于保证该字段有默认值。比如性别

PRIMARY KEY:主键,用于保证该字段的值非空且具有唯一性。比如学号、员工编号等

UNIQUE:唯一,用于保证该字段的值具有唯一性,可以为空。比如座位号

CHECK:检查约束【mysql中不支持】。比如年龄、性别

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

在从表添加外键约束,用于引用主表中某列的值。

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

添加约束的时机:

1.创建表时

2.修改表时

约束的添加分类:

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

表级约束:除了not null非空、default默认,其他的都支持

一、创建表时添加约束

1.添加列级约束

语法:直接在字段名和类型后面追加约束类型即可。

只支持:默认、非空、主键、唯一

CREATE DATABASE students;USE students;DROP TABLE stuinfo;CREATE TABLE major(id INT PRIMARY KEY,majorName VARCHAR(20)
);CREATE TABLE stuinfo(id INT PRIMARY KEY,    #主键stuName VARCHAR(20) NOT NULL,    #非空gender CHAR(1) CHECK(gender='男' OR gender ='女'),    #检查约束在mysql中没有效果seat INT UNIQUE,    #唯一age INT DEFAULT  18,    #默认约束,18为默认值majorId INT FOREIGN KEY REFERENCES major(id)    #外键,无效果
);DESC stuinfo;    #查看表结构SHOW INDEX FROM stuinfo;    #查看表中所有索引,主键、外键、唯一键会自动生成索引

2.添加表级约束

语法:在各个字段的最下面        【constraint 约束名】 约束类型(字段名)

DROP TABLE IF EXISTS stuinfo;CREATE TABLE stuinfo(id INT,stuname VARCHAR(20),gender CHAR(1),seat INT,age INT,majorid INT,    #注意写上逗号,因为下方还有语句CONSTRAINT pk PRIMARY KEY(id),    #主键,pk为主键名,由于mysql中主键名固定为PRIMARY,无法更改,因此此处pk无效果CONSTRAINT uq UNIQUE(seat),    #唯一键,uq为唯一键名CONSTRAINT ck CHECK(gender='男' OR gender='女'),    #检查CONSTRAINT fk_stuinfo_major FOREIGN KEY(majorid) REFERENCES major(id)    #外键
);SHOW INDEX FROM stuinfo;

通用的写法:★

CREATE TABLE IF NOT EXISTS stuinfo(id INT PRIMARY KEY,stuname VARCHAR(20),sex CHAR(1),age INT DEFAULT 18,seat INT UNIQUE,majorid INT,CONSTRAINT fk_stuinfo_major FOREIGN KEY(majorid) REFERENCES major(id)
);

主键和唯一键的大对比【面试题】

保证唯一性

是否允许为空

一个表中可以有多少个

是否允许组合

主键

×

至多有1个

组合主键

√,但不推荐

唯一键

可以有多个

组合唯一键

√,但不推荐

外键:

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

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

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

4.插入数据时,先插入主表,再插入从表

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

可以添加多个约束,无顺序要求,约束之间用空格隔开即可

二、修改表时添加约束

1.添加列级约束

alter table 表名 modify column 字段名 字段类型 新约束;

2.添加表级约束

alter table 表名 add 【constraint 约束名】 约束类型(字段名) 【外键的引用】;

案例:

1.添加非空约束(仅列级约束):

ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20)  NOT NULL;

2.添加默认约束(仅列级约束):

ALTER TABLE stuinfo MODIFY COLUMN age INT DEFAULT 18;

3.添加主键:

①列级约束

ALTER TABLE stuinfo MODIFY COLUMN id INT PRIMARY KEY;

②表级约束

ALTER TABLE stuinfo ADD PRIMARY KEY(id);

4.添加唯一:

①列级约束

ALTER TABLE stuinfo MODIFY COLUMN seat INT UNIQUE;

②表级约束

ALTER TABLE stuinfo ADD UNIQUE(seat);

5.添加外键(两种写法,但列级约束无效果,下方展示表级约束):

ALTER TABLE stuinfo ADD CONSTRAINT fk_stuinfo_major
FOREIGN KEY(majorid) REFERENCES major(id);

三、修改表时删除约束

1.删除非空约束:

ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20) NULL;
ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20);

2.删除默认约束:

ALTER TABLE stuinfo MODIFY COLUMN age INT;

3.删除主键:

ALTER TABLE stuinfo MODIFY COLUMN id INT;
ALTER TABLE stuinfo DROP PRIMARY KEY;

4.删除唯一:

ALTER TABLE stuinfo DROP INDEX seat;    #seat是唯一键的名字

5.删除外键:

ALTER TABLE stuinfo DROP FOREIGN KEY fk_stuinfo_major;

位置

支持的约束类型

(mysql中不支持检查约束)

是否可以起约束名

列级约束

列的后面

语法都支持,但外键没有效果

不可以

表级约束

所有列的下面

默认和非空不支持,其他支持

可以(主键没有效果)

标识列:又称为自增长列

含义:

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

特点:

1.标识列必须和主键搭配吗?不一定,但要求是一个key

2.一个表可以有几个标识列?至多一个!

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

4.标识列可以通过以下代码设置步长

SHOW VARIABLES LIKE '%auto_increment%';    #查看起始值和步长值SET auto_increment_increment=3;    #设置步长

起始值无法设置,如果要改变起始值,可以通过手动插入值,设置起始值

可以采用以下方法(假如起始值为10):

步骤1:

INSERT INTO tab_identity(id,NAME) VALUES(10,'john');

步骤2:

INSERT INTO tab_identity(id,NAME) VALUES(NULL,'john');

一、创建表时设置标识列

DROP TABLE IF EXISTS tab_identity;CREATE TABLE tab_identity(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(20),
);TRUNCATE TABLE tab_identity; (删除整个表的数据)INSERT INTO tab_identity(id,NAME) VALUES(NULL,'john');
#或INSERT INTO tab_identity(NAME) VALUES('lucy');SELECT * FROM tab_identity;

二、修改表时设置标识列

ALTER TABLE tab_identity MODIFY COLUMN id INT PRIMARY KEY AUTO_INCREMENT;

三、修改表时删除标识列(删除AUTO_INCREMENT,若已经有主键则删除PRIMARY KEY)

ALTER TABLE tab_identity MODIFY COLUMN id INT PRIMARY KEY;

八、TCL语言(事务控制语言)

*存储引擎(表类型):

概念:在mysql中的数据用各种不同的技术存储在文件(或内存)中

查看mysql支持的存储引擎:

show engines; 

在mysql中用的最多的存储引擎有: innodb、myisam、memory等,其中innodb支持事务,而myisam、memory等不支持事务

事务:

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

整个单独单元作为一个不可分割的整体,如果单元中某条sql语句一旦执行失败或产生错误,整个单元将会回滚(撤销所做的操作,回到最初的状态),所有受到影响的数据将返回到事务开始以前的状态;如果单元中的所有sql语句均执行成功,则事务被顺利执行。

事务的ACID属性:【面试题】

原子性(Atomicity):一个事务不可再分割,要么都执行要么都不执行

一致性(Consistency):一个事务执行会使数据从一个一致状态切换到另外一个一致状态

隔离性(Isolation):一个事务的执行不受其他事务的干扰(隔离级别)

持久性(Durability):一个事务一旦提交,则会永久的改变数据库的数据

事务的分类:

隐式事务:事务没有明显的开启和结束的标记。

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

显式事务:事务具有明显的开启和结束的标记。

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

SHOW VARIABLES LIKE 'autocommit';    #查看变量,发现“自动提交”开启

步骤1:开启事务

set autocommit=0;
start transaction;    #可选的,可写可不写,默认开启事务

步骤2:编写事务中的sql语句(select、insert、update、delete)

语句1;
语句2;
...

步骤3:结束事务(二选一)

commit;    #提交事务
rollback;    #回滚事务

事务的隔离级别:

事务并发问题的发生:

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

对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,如果没有采取必要的隔离机制,就会导致各种并发问题。

事务的并发问题:

脏读:对于两个事务T1、T2,T1读取了已经被T2更新但还没有被提交的字段。之后,若T2回滚,T1读取的内容就是临时且无效的。

不可重复读:对于两个事务T1、T2,T1读取了一个字段,然后T2更新了该字段。之后,T1再次读取同一个字段,值就不同了。

幻读:对于两个事务T1、T2,T1从一个表中读取了一个字段,然后T2在该表中插入了一些新的行。之后,如果T1再次读取同一个表,就会多出几行。

脏读和幻读注意区分:

二者都是一个事务读取数据时,另一个事务还未提交;

脏读针对更新,幻读针对插入或删除

数据库事务的隔离性:

数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题。

隔离级别:

一个事务与其他事务隔离的程度称为隔离级别。

数据库规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱。

数据库提供的4种事务隔离级别:

隔离级别

描述

READ UNCOMMITTED

读未提交数据

允许事务读取未被其他事务提交的变更。

脏读、不可重复读、幻读的问题都会出现。

READ COMMITTED

读已提交数据

只允许事务读取已经被其它事务提交的变更。

可以避免脏读,但不可重复读和幻读问题仍然可能出现。

REPEATABLE READ

可重复读

确保事务可以多次从一个字段中读取相同的值。

在这个事务持续期间,禁止其他事物对这个字段进行更新。

可以避免脏读和不可重复读,但幻读的问题仍然存在。

SERIALIZABLE

串行化

确保事务可以从一个表中读取相同的行。

在这个事务持续期间,禁止其他事务对该表执行插入、更新和删除操作。

所有并发问题都可以避免,但性能十分低下。

Oracle、Mysql支持的事务隔离级别和默认的事务隔离级别:

Oracle支持的2种事务隔离级别:READ COMMITED和SERIALIZABLE。

Oracle默认的事务隔离级别为READ COMMITED

Mysql支持4种事务隔离级别。

Mysql默认的事务隔离级别为 REPEATABLE READ

4种事务隔离级别案例演示:

设置隔离级别:

set session|global transaction isolation level 隔离级别名;
#session只针对当前连接有效,只在当前cmd窗口有效;
而global所有连接有效,所有cmd窗口有效,但需要重启

查看隔离级别:

select @@tx_isolation;
#以管理员身份运行cmd
net stop mysql
net start mysql
mysql -uroot -p123456
select @@tx_isolation;    #5.0版本
select @@transaction_isolation;    #8.0版本

事先建立数据库test和表account并插入数据:

CREATE DATABASE IF NOT EXISTS test;
USE test;DROP TABLE IF EXISTS account;
CREATE TABLE account(id INT PRIMARY KEY,username VARCHAR(10),balance INT
);
DESC account;INSERT INTO account VALUES(1,'张无忌',100);
INSERT INTO account VALUES(2,'赵敏',100);
SELECT * FROM account;

①隔离级别为最低的read uncommitted:允许事务读取未被其他事务提交的变更。

脏读、不可重复读、幻读的问题都会出现。

测试:

以管理员身份运行cmd,查看当前隔离级别,发现为repeatable read,因此先修改事务的隔离级别为read uncommitted。运行test库,开启一个事务,在该事务下更新account表中username的值,但不要提交事务。

select @@transaction_isolation;    #查看当前隔离级别
set session transaction isolation level read uncommitted;    #修改隔离级别
select @@transaction_isolation;    #查看当前隔离级别use test;
select * from account;
set autocommit=0;    #开启事务
update account set username='john';    #编写事务中的sql语句,事务开启但并未提交

重新以管理员身份运行cmd,查看当前隔离级别仍为repeatable read,因此先修改事务的隔离级别为read uncommitted,再次运行test库,开启一个事务,在该事务下使用select语句查看account表中的数据,此时读到的数据就是脏数据。(此时,若在第一个cmd窗口中回滚事务,再在第二个cmd窗口中运行select语句,发现读到的仍为未修改之前的数据,该现象也可以称为不可重复读和幻读。)

②隔离级别为read committed:只允许事务读取已经被其它事务提交的变更。

可以避免脏读,但不可重复读和幻读问题仍然可能出现。

测试:

以管理员身份运行cmd,修改隔离级别为read committed,开启事务,对test库account表中数据进行更新,但不要提交事务。再以管理员身份运行cmd,修改隔离级别为read committed,开启事务,查看test库account表中数据,发现仍为未更新的数据,说明read commit可以避免脏读。

此时若在第一个cmd窗口提交事务,再在第二个cmd窗口查询account表中数据,发现表中数据发生改变,说明当隔离级别是read commit时,不可重复读。

③隔离级别为repeatable read:确保事务可以多次从一个字段中读取相同的值。

在这个事务持续期间,禁止其他事物对这个字段进行更新。

可以避免脏读和不可重复读,但幻读的问题仍然存在。

测试:

以管理员身份运行cmd,修改隔离级别为repeatable read,开启一个事务,执行更新操作,更新表中username都为mmmm,先不执行,此时本应该有2行受到影响;

再以管理员身份运行cmd,修改隔离级别为repeatable read,开启另一个事务,执行插入操作且提交事务,此时执行第一个cmd窗口中的更新操作,发现3行受到影响,说明数据幻读。

④隔离级别为serializable:确保事务可以从一个表中读取相同的行。

在这个事务持续期间,禁止其他事务对该表执行插入、更新和删除操作。

所有并发问题都可以避免,但性能十分低下。

测试:

以管理员身份运行cmd,修改隔离级别为serializable,开启一个事务,执行更新操作,更新表中username都为ww,先不执行;

再以管理员身份运行cmd,修改隔离级别为serializable,开启另一个事务,执行插入操作,发现无法插入,直到第一个cmd窗口中的事务被提交才能继续在第二个cmd窗口中执行插入操作,说明serializable避免幻读。

演示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;    #回滚到保存点
SELECT * FROM account;    #25号删,28号没删

演示事务对于delete和truncate的处理的区别:

演示delete:支持回滚

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

演示truncate:不支持回滚

SET autocommit=0;
START TRANSACTION;
TRUNCATE TABLE account;
ROLLBACK;
SELECT * FROM account;

九、视图

视图∶

MySQL从5.0.1版本开始提供视图功能。一种虚拟存在的表,行和列的数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的,只保存了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 stuname,majorname
FROM stuinfo s
INNER JOIN major m ON s.`majorid`= m.`id`;
SELECT * FROM v1 WHERE stuname LIKE '张%';

一、创建视图

语法:

create view 视图名 as 查询语句;

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

#使用视图
create view v1 as
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;    #创建视图,多表连接
select * from v1 where last_name like ‘%a%’;

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

#不用视图
select ag_dep.ag,j.grade_level from job_grades j
inner join (select avg(salary) ag,department_id
from employees group by department_id) ag_dep
on ag_dep.ag between j.lowest_sal and j.highest_sal;
#使用视图
create view v2 as
select avg(salary) ag,department_id from employees
group by department_id;select v2.ag, j.grade_level
from v2
inner join job_grades j
on v2.ag between j.lowest_sal and j.highest_sal;

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

SELECT * FROM v2 ORDER BY ag LIMIT 1;    #默认升序排列

案例4:查询平均工资最低的部门名和工资(或将案例3查询结果创建为新视图v3)

select d.department_name,aa.ag from departments d
inner join (SELECT * FROM v2 ORDER BY ag LIMIT 1) aa
on d.department_id=aa.department_id;

二、修改视图

方式一:

create or replace view  视图名 as 查询语句;

方式二:

alter view 视图名 as 查询语句;

三、删除视图

drop view 视图名,视图名,...;

四、查看视图(结构)

方式一:

DESC 视图名;

方式二:

SHOW CREATE VIEW myv3;    #sqlyog中效果不好,在cmd窗口使用

五、更新视图(同时对原始表也进行了更新)

往往对视图添加权限,使其只能读不允许更新,从而不对原始表产生更新

1.插入:

INSERT INTO myv1 VALUES('张飞','zf@qq.com');

2.修改:

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

3.删除:

DELETE FROM myv1 WHERE last_name = '张无忌';

❤具备以下特点的视图不允许更新:

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

②常量视图

CREATE OR REPLACE VIEW myv2 AS SELECT 'john' NAME;
SELECT * FROM myv2;
UPDATE myv2 SET NAME='lucy';    #报错

③Select中包含子查询

CREATE OR REPLACE VIEW myv3 AS
SELECT (SELECT MAX(salary) FROM employees) 最高工资;
SELECT * FROM myv3;
UPDATE myv3 SET 最高工资=100000;    #报错

④join

⑤from一个不能更新的视图

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

如:查询所有领导的信息

CREATE OR REPLACE VIEW myv6 AS
SELECT last_name,email,salary FROM employees
WHERE employee_id IN(SELECT manager_id FROM employees WHERE manager_id IS NOT NULL);
SELECT * FROM myv6;
UPDATE myv6 SET salary=10000 WHERE last_name = 'k_ing';    #报错

视图和表的区别:

创建语法的关键字

是否实际占用物理空间

使用

视图

create view

只是保存了逻辑,未保存数据

增删改查,一般不能增删改

create table

保存了数据

增删改查

视图的好处:

重用sql语句,效率高

简化复杂的sql操作,不必知道它的查询细节

和表实现了分离,保护数据,提高安全性

十、变量

系统变量:

全局变量

会话变量

自定义变量:

用户变量

局部变量

一、系统变量

说明:

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

注意:

全局变量需要添加global关键字,会话变量需要添加session关键字;如果不写,默认会话级别

使用步骤:

1.查看所有的系统变量

show global|【session】variables;

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

show global|【session】 variables like '%char%';

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

select @@global|【session】.系统变量名;

4.为某个系统变量赋值

方式一:

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

方式二:

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

1》全局变量

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

①查看所有全局变量:

SHOW GLOBAL VARIABLES;

②查看满足条件的部分系统变量:

SHOW GLOBAL VARIABLES LIKE '%char%';

③查看指定的系统变量的值:

SELECT @@global.autocommit;

④为某个系统变量赋值

SET @@global.autocommit=0;
SET GLOBAL autocommit=0;

2》会话变量

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

①查看所有会话变量:

SHOW SESSION VARIABLES;

②查看满足条件的部分会话变量:

SHOW SESSION VARIABLES LIKE '%char%';

③查看指定的会话变量的值

SELECT @@autocommit;
SELECT @@session.tx_isolation;

④为某个会话变量赋值

SET @@session.tx_isolation='read-uncommitted';
SET SESSION tx_isolation='read-committed';

二、自定义变量

说明:

变量由用户自定义,而不是系统提供的

使用步骤:

1.声明

2.赋值

3.使用(查看、比较、运算等)

1》用户变量

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

赋值操作符:=或:=

①声明并初始化

SET @变量名=值;
#或
SELECT @变量名:=值;

②赋值(更新变量的值)

方式一:

SET @变量名=值;
#或
SET @变量名:=值;
#或
SELECT @变量名:=值;

方式二:

SELECT 字段 INTO @变量名 FROM 表;

③使用(查看变量的值):SELECT @变量名;

案例:

set @count=1;    #声明并初始化
select count(*) into @count from employees;    #赋值
select @count;    #使用

2》局部变量

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

①声明

DECLARE 变量名 类型;
DECLARE 变量名 类型 【DEFAULT 值】;

②赋值(更新变量的值)

方式一:通过set或select

SET 局部变量名=值;
#或
SET 局部变量名:=值;
#或
SELECT @局部变量名:=值;

方式二:通过select into

SELECT 字段 INTO 局部变量名 FROM 表;

③使用(查看变量的值):

SELECT 局部变量名;

对比用户变量和局部变量:

作用域

定义和使用的位置

语法

用户变量

当前会话

会话中的任何地方

必须加@符号,不用限定类型

局部变量

begin end中

只能在begin end中,

且为第一句话

一般不用加@符号,需要限定类型

案例:声明两个变量并附初值,求和,并打印(打印就是select)

1.用户变量

set @m=1;

set @n=2;

set @sum=@m+@n;

select @sum;

2.局部变量(未在begin end中,会报错)

declare m int default 1;

declare n int default 2;

declare sum int;

set sum =m+n;

select sum;

十一、存储过程和函数

存储过程和函数:类似于java中的方法

好处:1.提高代码的重用性 2.简化操作

存储过程

含义:

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

好处:

1.提高代码的重用性

2.简化操作

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

(已经调用过就意味着已经编译了,第二次调用时就不用再编译了)

一、创建语法

语法:

CREATE PROCEDURE 存储过程名(参数列表)
BEGIN存储过程体(一组合法的SQL语句)
END

注意:

1.参数列表包含三部分:参数模式  参数名  参数类型

举例:

in stuname varchar(20)

参数模式:(SQLyog中不支持该写法,在SQL客户端尝试)

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

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

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

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

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

存储过程的结尾可以使用 delimiter 重新设置(避免与;混淆)

语法:delimiter 结束标记

案例:

delimiter $

二、调用语法

语法:

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

案例演示:

1.空参列表

案例:插入到admin表中五条记录

#SELECT * FROM admin;    #查看admin表中的记录DELIMITER $    #结束标记的设置CREATE PROCEDURE myp1()    #创建
BEGININSERT INTO admin(username,`password`)VALUES('john1','0000'),('lily','0000'),('rose','0000'),('jack','0000'),('tom','0000');
END $CALL myp1()$    #调用,注意结束标记都使用$

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

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

CREATE PROCEDURE myp2(IN beautyName VARCHAR(20))
BEGINSELECT bo.*FROM boys boRIGHT JOIN beauty b ON bo.id = b.boyfriend_idWHERE b.name=beautyName;
END $
CALL myp2('柳岩')$    #调用

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

CREATE PROCEDURE myp4(IN username VARCHAR(20),IN PASSWORD VARCHAR(20))
BEGINDECLARE result INT DEFAULT 0;    #声明并初始化SELECT COUNT(*) INTO result    #赋值FROM adminWHERE admin.username = usernameAND admin.password = PASSWORD;SELECT IF(result>0,'成功','失败');    #使用
END $CALL myp3('张飞','8888')$    #调用

3.创建out 模式参数的存储过程

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

CREATE PROCEDURE myp6(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20))
BEGINSELECT bo.boyname INTO boyNameFROM boys boRIGHT JOINbeauty b ON b.boyfriend_id = bo.idWHERE b.name=beautyName ;
END $SET @bName$    #定义用户变量,可以应用在begin end外面CALL myp5('小昭', @bName) $    #调用
#或
CALL myp5('小昭', @bName) $    #调用SELECT @bName$

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

CREATE PROCEDURE myp7(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20),OUT userCP INT)
BEGINSELECT bo.boyname,bo.usercp INTO boyName,userCPFROM boys boRIGHT JOINbeauty b ON b.boyfriend_id = bo.idWHERE b.name=beautyName ;
END $CALL myp7('小昭',@name,@cp)$    #调用SELECT @name,@cp$

4.创建带inout模式参数的存储过程

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

CREATE PROCEDURE myp8(INOUT a INT ,INOUT b INT)
BEGINSET a=a*2;    #局部变量的赋值SET b=b*2;
END $SET @m=10$    #定义两个用户变量
SET @n=20$CALL myp8(@m,@n)$    #调用SELECT @m,@n$

三、删除存储过程

语法:

drop procedure 存储过程名
DROP PROCEDURE p1;
DROP PROCEDURE p2,p3;    #报错

四、查看存储过程的信息

DESC myp2;    #报错SHOW CREATE PROCEDURE  myp2;

函数

含义:

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

好处:

1.提高代码的重用性

2.简化操作

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

区别:

存储过程:可以有0个返回,也可以有多个返回,适合做批量插入、批量更新

函数:有且仅有1 个返回,适合做处理数据后返回一个结果

一、创建函数

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

语法:

CREATE FUNCTION 函数名(参数名 参数类型,...) RETURNS 返回类型
BEGIN函数体(最后一句:return 返回值;)
END

注意:

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

2.函数体:肯定会有return语句,如果没有会报错

如果return语句没有放在函数体的最后也不报错,但不建议

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

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

二、调用函数

SELECT 函数名(实参列表)

❤查看所有创建的存储过程和函数的基本信息:mysql->proc->右击->打开表

案例演示:

1.无参有返回

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

CREATE FUNCTION myf1() RETURNS INT    #创建
BEGINDECLARE 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
BEGINSET @sal=0;    #定义用户变量SELECT salary INTO @sal    #赋值FROM employeesWHERE last_name = empName;RETURN @sal;
END $SELECT myf2('Kochhar') $    #调用

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

CREATE FUNCTION myf3(deptName VARCHAR(20)) RETURNS DOUBLE
BEGINDECLARE sal DOUBLE;SELECT AVG(salary) INTO salFROM employees eINNER JOIN departments d ON e.department_id=d.department_idWHERE d.department_name=deptName;RETURN sal;
END $SELECT myf3('IT')$    #调用

三、查看函数

SHOW CREATE FUNCTION myf3;

四、删除函数

DROP FUNCTION myf3;

函数和存储过程的区别

关键字

调用语法

返回值

应用场景

函数

FUNCTION

SELECT 函数()

只能是一个

一般用于查询结果为一个值并返回时,

当有返回值而且仅仅一个

存储过程

PROCEDURE

CALL 存储过程()

可以有0个或多个

一般用于更新

十二、流程控制结构

顺序结构:程序从上往下依次执行

分支结构:程序从两条或多条路径中选择一条去执行

循环结构:程序在满足一定条件的基础上,重复执行一段代码

顺序结构

分支结构

一、if函数

功能:实现简单的双分支

语法:

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

执行顺序:如果表达式1成立,则if函数返回表达式2的值,否则返回表达式3的值

应用:任何地方

二、case结构

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

语法:

case 变量|表达式|字段when 要判断的值 then 返回的值1或语句1    #若返回的值是语句,需要加;when 要判断的值 then 返回的值2或语句2...else 要返回的值n
end 【case】;    #若返回的值是语句,需要加case

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

语法:

casewhen 要判断的条件1 then 返回的值1或语句1    #若返回的值是语句,需要加;when 要判断的条件2 then 返回的值2或语句2...else 要返回的值n或语句n或语句n
end 【case】;    #若返回的值是语句,需要加case

特点:

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

可以作为独立的语句去便用,只能放在BEGIN END中

②如果when中的值满足,则执行对应的then后面的语句并且结束case

如果都不满足,则执行else中的语句或值

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

三、if结构

功能:实现多重分支

语法:

if 条件1 then 语句1;
elseif 条件2 then 语句2;
...
【else 语句n;】
end if

应用场合:只能用在begin end中

三者比较:

应用场合

if函数

简单双分支

case结构

等值判断的多分支

if结构

区间判断的多分支

循环结构

分类:

while、loop、repeat

循环控制:

iterate:类似于continue,继续,结束本次循环,继续下一次

leave:类似于break,跳出,结束当前所在的循环

一、while

语法:

【标签:】WHILE 循环条件  DO循环体;
END WHILE 【标签】;

二、loop

语法:

【标签:】LOOP循环体;
END LOOP【标签】;

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

要想跳出循环,需要搭配leave使用

三、repeat

语法:

【标签:】REPEAT循环体;UNTIL 结束循环的条件;
END REPEAT【标签】;

特点:

只能放在BEGIN END里面

如果要搭配leave跳转语句,需要使用标签,否则可以不用标签

leave类似于java中的break语句,跳出所在循环!!!

MySQL学习笔记(B站网课:MySQL_基础+高级篇- 数据库 -sql -mysql教程_mysql视频_mysql入门_尚硅谷)已完结相关推荐

  1. MySQL_基础+高级篇- 数据库 -sql -mysql教程_mysql视频_mysql入门_尚硅谷2

    34_92from后面使用子查询 #from后面/*将结果当作一张表,所以需要起别名不然用不了 */#案例:查询每个部门的平均工资的工资等级#首先把每个部门的平均工资查出来 SELECT AVG(sa ...

  2. MySQL学习笔记-B站动力节点

    文章目录 MySQL Day1 1.概述 2.sql.DB.DBMS分别是什么?他们之间的关系? 3.表 4.sql语句分类 5.导入数据 6.sql脚本 7.删除数据库命令 8.查看表结构 9.查看 ...

  3. mysql学习笔记-1 【路飞学城6天学会数据库课程】

    Mysql安装配置 环境变量配置及系统服务制作 """ 1.查看当前具体进程tasklisttasklist | findstr mysqld2.杀死具体进程taskki ...

  4. 学习笔记(01):ZStack 带你0基础搭建私有云平台|ZCCT实战培训视频|-云计算基础技术及解决方案介绍...

    立即学习:https://edu.csdn.net/course/play/27985/381170?utm_source=blogtoedu 一.云计算定义与特点 1.按需支付 2.成本低 3.周期 ...

  5. 学习笔记(02):ZStack 带你0基础搭建私有云平台|ZCCT实战培训视频|-ZStack产品与解决方案介绍...

    立即学习:https://edu.csdn.net/course/play/27985/381171?utm_source=blogtoedu 目标 产品愿景 优化管理 .创新

  6. Mysql学习笔记(六)增删改查

    原文:Mysql学习笔记(六)增删改查 PS:数据库最基本的操作就是增删改查了... 学习内容: 数据库的增删改查 1.增...其实就是向数据库中插入数据.. 插入语句 insert into tab ...

  7. 【自动控制原理_B站网课笔记】第一章自动控制的一般概念part2

    本视频对应B站网课:https://www.bilibili.com/video/BV135411s7RF 文章目录 水位控制系统 转速控制系统 水位控制系统 被控对象:水池(含阀门) 被控量(输出) ...

  8. Mysql学习笔记(基础)基础sql语句详细记录

    数据库学习(基础) // 个人网课学习记录,如果有违规等问题,请联系我删除~ mysql下载安装( 解压版安装配置 下载版安装配置 ) 需求分析:使用cmd命令来创建一个数据库,并对数据库中得一张分类 ...

  9. Redis学习笔记(B站狂神说)(自己总结方便复习)

    Redis学习笔记B站狂神说 redis: 非关系型数据库 一.NoSQL概述 1.为什么要用Nosql 1.单机Mysql的年代 思考一下,这种情况下:整个网站的瓶颈是什么? 1.数据量如果太大,一 ...

最新文章

  1. 【SICP练习】104 练习3.1-3.4
  2. PandaRSS 自助服务系统安装配置
  3. 第二讲,我们来谈谈:“什么是二进制”
  4. 我是一只IT小小鸟读书笔记
  5. 深度学习(三十二)——AlphaGo, AlphaStar
  6. SAP Commerce Cloud 新一代 UI Spartacus 和 Customer Data cloud 的集成
  7. for myself
  8. bzoj 2435: [Noi2011]道路修建(DFS)
  9. FFDshow video encoder -CLSID
  10. 电脑屏幕变黄如何调整_办公室照明设计如何避免踩坑,四个要点必须注意
  11. Stanford CoreNLP依存关系分析、词性标注及句子主语分析(使用Python) 超详细截图手把手教学,新手友好
  12. php ckfinder 无效请求.,解决nginx和php使用ckfinder无法上传大文件的问题
  13. 植物大战僵尸 - 修改关卡和商店金钱
  14. RN Error: 无法获取此包的编译时间戳。请更新react-native-update到最新版本后重新打包上传。
  15. regedit参数+批处理修改IE标题
  16. 公司申请微信订阅号需要的材料及注意事项
  17. html如何添加时钟效果,五步轻松实现JavaScript HTML时钟效果
  18. Flutter之微信支付实战模板
  19. proteus仿真数码管
  20. 计算方法 1.绪论,误差

热门文章

  1. 各类游戏开发者看过来,你的游戏安全问题解决了吗?【内附《游戏安全白皮书》下载】
  2. n行Python代码系列:四行程序实现两个视频同屏播放
  3. yum、apt-get、dnf
  4. rpm和yum/dnf 安装方式与区别
  5. Redis是单线程还是多线程问题
  6. oppo R9s 远程刷机 成功 使用到的软件记录
  7. YOLOv8实践 | 手把手训练教学及YOLOv8的多任务使用
  8. 我的世界服务器反作弊怎么修改,我的世界如何利用命令方块反作弊 反作弊命令攻略...
  9. .NET Core Ocelot Consul
  10. Java工具-获取某月份天数、某月最后一天、某月工作日天数(支持自定义节假日)