MySQL学习笔记(B站网课:MySQL_基础+高级篇- 数据库 -sql -mysql教程_mysql视频_mysql入门_尚硅谷)已完结
目录
一、为什么要学习数据库
二、数据库的相关概念
三、数据库存储数据的特点
四、初始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入门_尚硅谷)已完结相关推荐
- MySQL_基础+高级篇- 数据库 -sql -mysql教程_mysql视频_mysql入门_尚硅谷2
34_92from后面使用子查询 #from后面/*将结果当作一张表,所以需要起别名不然用不了 */#案例:查询每个部门的平均工资的工资等级#首先把每个部门的平均工资查出来 SELECT AVG(sa ...
- MySQL学习笔记-B站动力节点
文章目录 MySQL Day1 1.概述 2.sql.DB.DBMS分别是什么?他们之间的关系? 3.表 4.sql语句分类 5.导入数据 6.sql脚本 7.删除数据库命令 8.查看表结构 9.查看 ...
- mysql学习笔记-1 【路飞学城6天学会数据库课程】
Mysql安装配置 环境变量配置及系统服务制作 """ 1.查看当前具体进程tasklisttasklist | findstr mysqld2.杀死具体进程taskki ...
- 学习笔记(01):ZStack 带你0基础搭建私有云平台|ZCCT实战培训视频|-云计算基础技术及解决方案介绍...
立即学习:https://edu.csdn.net/course/play/27985/381170?utm_source=blogtoedu 一.云计算定义与特点 1.按需支付 2.成本低 3.周期 ...
- 学习笔记(02):ZStack 带你0基础搭建私有云平台|ZCCT实战培训视频|-ZStack产品与解决方案介绍...
立即学习:https://edu.csdn.net/course/play/27985/381171?utm_source=blogtoedu 目标 产品愿景 优化管理 .创新
- Mysql学习笔记(六)增删改查
原文:Mysql学习笔记(六)增删改查 PS:数据库最基本的操作就是增删改查了... 学习内容: 数据库的增删改查 1.增...其实就是向数据库中插入数据.. 插入语句 insert into tab ...
- 【自动控制原理_B站网课笔记】第一章自动控制的一般概念part2
本视频对应B站网课:https://www.bilibili.com/video/BV135411s7RF 文章目录 水位控制系统 转速控制系统 水位控制系统 被控对象:水池(含阀门) 被控量(输出) ...
- Mysql学习笔记(基础)基础sql语句详细记录
数据库学习(基础) // 个人网课学习记录,如果有违规等问题,请联系我删除~ mysql下载安装( 解压版安装配置 下载版安装配置 ) 需求分析:使用cmd命令来创建一个数据库,并对数据库中得一张分类 ...
- Redis学习笔记(B站狂神说)(自己总结方便复习)
Redis学习笔记B站狂神说 redis: 非关系型数据库 一.NoSQL概述 1.为什么要用Nosql 1.单机Mysql的年代 思考一下,这种情况下:整个网站的瓶颈是什么? 1.数据量如果太大,一 ...
最新文章
- 【SICP练习】104 练习3.1-3.4
- PandaRSS 自助服务系统安装配置
- 第二讲,我们来谈谈:“什么是二进制”
- 我是一只IT小小鸟读书笔记
- 深度学习(三十二)——AlphaGo, AlphaStar
- SAP Commerce Cloud 新一代 UI Spartacus 和 Customer Data cloud 的集成
- for myself
- bzoj 2435: [Noi2011]道路修建(DFS)
- FFDshow video encoder -CLSID
- 电脑屏幕变黄如何调整_办公室照明设计如何避免踩坑,四个要点必须注意
- Stanford CoreNLP依存关系分析、词性标注及句子主语分析(使用Python) 超详细截图手把手教学,新手友好
- php ckfinder 无效请求.,解决nginx和php使用ckfinder无法上传大文件的问题
- 植物大战僵尸 - 修改关卡和商店金钱
- RN Error: 无法获取此包的编译时间戳。请更新react-native-update到最新版本后重新打包上传。
- regedit参数+批处理修改IE标题
- 公司申请微信订阅号需要的材料及注意事项
- html如何添加时钟效果,五步轻松实现JavaScript HTML时钟效果
- Flutter之微信支付实战模板
- proteus仿真数码管
- 计算方法 1.绪论,误差
热门文章
- 各类游戏开发者看过来,你的游戏安全问题解决了吗?【内附《游戏安全白皮书》下载】
- n行Python代码系列:四行程序实现两个视频同屏播放
- yum、apt-get、dnf
- rpm和yum/dnf 安装方式与区别
- Redis是单线程还是多线程问题
- oppo R9s 远程刷机 成功 使用到的软件记录
- YOLOv8实践 | 手把手训练教学及YOLOv8的多任务使用
- 我的世界服务器反作弊怎么修改,我的世界如何利用命令方块反作弊 反作弊命令攻略...
- .NET Core Ocelot Consul
- Java工具-获取某月份天数、某月最后一天、某月工作日天数(支持自定义节假日)