基础篇
去除重复行
SELECT DISTINCT 名
FROM 表
空值参与运算
- 空值:null
- Null不等同于0,‘’,‘null’
- 空值参与运算结果一定也为空
实际问题的解决方案:引入IFNULL
例:SELECT employee_id,salary “月工资”,salary*(1+IFNULL(commission_pct,0))*12 “年工资”,commission
FROM employees;
着重号 ····` `
避免与表名或者关键字重名,所以加着重号表示只是普通的名
查询常数
一般来说我们只从一个表中查询数据,通常不需要增加一个固定的常数列,但如果我们想整合不同的数据源,用常数列作为这个表的标记,就需要查询常数
例: 显示表departments 的结构,并查询其中的全部数据
DESCRIBE departments
SELECT *
FROM departments;
显示表的结构
DESCRIBE 表名 //显示了表中字段的详细信息 显示表的结构
也可简写 DESC 表明
过滤数据
例:只查询90号部门员工信息
SELECT *
FROM 表名
//过滤条件
WHERE ID=90;
运算符
算术运算符:+ - * / %
代码运行: SELECT A+B,A-C,A*B,A/B,A%B
FROM 表
//在SQL 中,+没有连接作用,就表示加法运算,即便后面数字用单引号表示,此时也会将字符串转换为数值(隐式转换),如果后面是非数字则当成零来看待,若为null则结果为null
比较运算符:= ó(安全等于,与=区别是此符号可以用来对null进行判断) <> != < <= > >=
代码运行:SELECT 比较数值
FROM 表名
//字符串存在隐式转换,如果转换数值不成功,则看作零 如果两边都是字符串的话,则按照ANSI码的比较规则进行比较 如果有null参与判断,结果就为null
逻辑运算符:OR || 或 AND && 且 NOT ! 非 XOR 异或(追求的‘异‘)
//AND 的优先级要高于OR
位运算符(了解即可) &按位与 |按位或 ^按位异或 ~按位取反 >>按位右移 <<按位左移
//位运算是在二进制上进行计算的运算符,位运算符先将操作数变成二进制数,然后进行位运算,最后将计算结果从二进制变回十进制数
关键字
不在条件内的可直接在条件前加NOT _下划线代表一个不确定字符 转义字符 \
判断null
IS NULL查询是null
IS NOT NULL 查询不是null
判断大小
LEAST 判断最小
GREATEST 判断最大
查询条件下节点1和条件上节点2范围内的数据
BETWEEN 条件1 AND 条件2
查询具体数据
IN(数据,数据…)
模糊查询
LIKE ‘%条件%’
//代码中前面要加WHERE的
//% 代表不确定的字符数量 如果查询条件为字符,前面没有添加%则是查询到用此字符为开头的,若结尾没有添加%则是查询到用此字符结尾的数据
正则表达式
REGEXP \RLIKE
代码:SELECT 条件 REGEXP 规则
‘^’代表以此为开头的字符
‘$‘代表以此为结尾的字符
‘.‘代表匹配任何一个单字符
排序
//如果没有使用排序操作。默认情况下查询返回的数据是按照添加数据的顺序显示的
//排序中默认是升序
//排序可以使用列的别名,但因为先后顺序的缘故,WHERE是不可以使用别名的,并且WHERE和ORDER BY连用时WHERE需要声明在FROM后,ORDER BY之前
升序:ASC(从小到大)
降序:DESC(从大到小)
代码运行 例:SELECT 条件
FROM 表名
ORDER BY 需要排序的条件 升序/降序;
二级排序
代码运行: 例: SELECT 条件
FROM 表名
ORDER BY 排序条件 DESC,排序条件 ASC;
多列排序
同上,在后添加排序条件
分页
LIMIT实现数据分页
公式:LIMIT(pageNo-1)*pageSize,pageSize;
代码运行:SELECT 条件
FROM 表名
LIMIT 开始的数,分页的个数;
多表查询
多表查询需要有连接条件,需要把查询中所用到的表都连接起来(连接条件就是两个表共有的条件),例如倘若有n个表实现多表查询,则需要至少n-1个连接条件
代码运行 例:SELECT 条件
FROM 表
WHERE 连接条件 例如:employees.id=departments.id
表名.连接条件=另一个表名.连接条件
//如果查询语句中出现了多个表中都存在的字段,则必须指明此字段所在的表
建议:从sql优化的角度,建议对标查询时,每个字段前都指明其所在的表(就是在SELECT后的条件中加上你条件所在的那个表)
代码中字段麻烦可为表起别名(就是在FROM后的表名后加上自己想要用的别名)而且如果给表起了别名,一旦在SELECT和WHERE中使用了别名的话,则必须一直使用别名,不可以再使用表名,二者不可以混用
多表查询的分类
角度一:等值连接 vs 非等值连接(就是谁等于谁的那种就是等值连接 大于小于就是非等于)
角度二:自连接 vs 非自连接(就是自己和自己进行连接)
角度三:内连接 vs 外连接
内连接:合并具有同一列的两个以上的表的行,结果集中不包含一个表与另一个表不匹配的行
外连接:合并具有同一列的两个以上的表的行,结果集中除了包含一个表与另一个表匹配的行之外,还查询到了左表或右表中不匹配的行
外连接的分类:左外连接、右外连接、满外连接
左外连接:两个表在连接过程中除了返回满足连接条件的行以外还返回左表中不满足条件的行,即为左外连接
右外连接:两个表在连接过程中除了返回满足连接条件的行以外还返回右表中不满足条件的行,即为右外连接
(只要出现所有就一定是外连接)
SQL92语法实现外连接使用‘+’
SQL99语法使用JOIN…IN实现多表查询(JOIN存在FROM中,放在表名和表名之间,ON则用于连接条件)LEFT JOOIN…ON左外连接 RIGHT JOIN…ON右外连接 FULL OUTER JOIN 满外连接
UNION和UNION ALL的使用(合并数据用)
UNION:会执行去重操作
UNION ALL:不会执行去重操作
结论:如果明确知道合并数据后的结果数据不存在重复数据,或者不需要去除重复的数据,则尽量使用UNION ALL语句,以提高数据查询的效率
七种JOIN
内连接、左外连接、右外连接(左右的就是查的哪边的就用哪个,看FORM中的顺序)、左实右空、左空右实(哪个空就在下方WHERE 中定义哪个为空)、满外连接(合并上面刚好可以凑齐完整的数据)、中间空(同满)
自然连接
NATURAL JOIN:它会帮助你自动查询两张连接表中所有相同的字段,然后进行等值连接
用法:加在FROM 中连接表中间
好处:简洁
坏处:不够灵活(了解即可)
USING 连接
使用条件:同名字段
不适用于自连接
单行函数 !!!单行函数可以嵌套使用
//函数需要自行查询,按照例子自行理解加使用吧
聚合函数 MYSQL!!!聚合函数不允许嵌套使用
常见的几个聚合函数
- AVG/SUM:只适用于数值类型的字段(或变量)
- MAX/MIN:适用于数值类型、字符串类型、日期时间类型字段(或变量)
- COUNT:
作用:计算指定字段在查询结构中出现的个数(查询个数)
注意:计算指定字段出现的个数时,是不计算NULL值的
- GROUP BY :用于分组
结论:SELECT中出现的非组函数的字段必须声明在GROUP BY中
反之,GROUP BY中声明的字段可以不出现在SELECT中
另外GROUP BY 声明在FROM后面、WHERE后面,ORDER BY前面、LIMIT前面
- HAVING:用于过滤数据
如果过滤条件中使用了聚合函数,则必须使用HAVING来替换WHERE,否则,报错
HAVING的使用前提是和GROUP BY一起使用
WHERE与HAVING 的对比
- WHERE可以直接使用表中的字段作为筛选的条件,但不能使用分组中的计算函数作为筛选条件;HAVING必须要与GROUP BY配合使用,可以把分组计算的函数和分组字段作为筛选
- 如果需要通过连接从关联表中获取需要的数据,WHERE是先筛选后连接,而HAVING是先连接后筛选
SQL底层执行原理
SELECT语句的完整结构
Sq192语法
SELECT…………………..(存在聚合函数)
FROM……………………
WHERE 多表的连接条件 AND不包含聚合函数的过滤条件
GROUP BY …………….
HAVING 包含聚合函数的过滤条件
ORDER BY ……………(ASC/DESC)
LIMIT…………..
Sq199语法
SELECT…………………..(存在聚合函数)
FROM……(LEFT/RIGHT)JOIN……ON 多表的连接条件
(LEFT/RIGHT)JOIN……ON……..
WHERE 不包含聚合函数的过滤条件
GROUP BY …………….
HAVING 包含聚合函数的过滤条件
ORDER BY ……………(ASC/DESC)
LIMIT…………..
SQL语句的执行过程
FROM……——>ON——>(LEFT/RIGNT JOIN)——>WHERE——>GROUP BY——>HAVING——>SELECT——>DISTINCT——>ORDER BY——>LIMIT
子查询
代码运行 例:SELECT last_name,salary
FROM employees
WHERE salary>(
SELECT salary
FROM employees
WHERE last_name=’Abel’
);
称谓的规范:外查询(或主查询)、内查询(或子查询)
//子查询(内查询)在主查询之前一次执行完成
//子查询的结果被主查询(外查询)使用
注意事项:
- 子查询要包括在括号内
- 将子查询放在比较条件的右侧
- 单行操作符对应单行子查询,多行操作符对应多行子查询
子查询的分类
角度一:从内查询返回的结果的条目数
单行子查询 vs 多行子查询
角度二:内查询是否被执行多次
相关子查询 vs 不相关子查询
单行子查询(就是只出现一行结果)
单行操作符:= != > >= < <=
多行子查询(就是出现多行结果)
多行比较操作符:
IN(等于列表中的任意一个) //就相当于是单行子查询中的等于号
ANY(需要和单行比较操作符一起使用,和子查询返回的某一个值比较)//要求中存在任一则就用ANY
ALL (需要和单行比较操作符一起使用,和子查询返回的所有值比较) //要求中存在所有则用ALL
SOME(实际上是ANY的别名,作用相同,一般常使用ANY)
空值问题(如果结果中存在NULL值且是所需结果则需声明去除NULL值的存在)
EXISTS 运算符用于判断查询子句是否有记录,如果有一条或多条记录存在返回 True,否则返回 False
创建和管理表
创建数据库
方式一:
代码运行 例:CREATE DATABASE 名;
方式二:显示了指名了要创建的数据库的字符集
代码运行 例:CREATE DATABASE 名 CHARACTER SET ‘gbk’;
方式三:如果要创建的数据库已经存在,则创建不成功,但不会报错,如果创建的数据库不存在则创建成功(推荐使用)
代码运行 例:CREATE DATABASE IF NOT EXISTS名 CHARACTER SET ‘utf8’;
管理数据库
- 查看当前连接中数据库都有哪些
SHOW DATABASES;
- 切换数据库
USE 库名;
- 查看当前数据库中保存的数据表
SHOW TABLES;
- 查看当前使用的数据库
SELECT DATABASE() FROM DUAL;
- 查看创建数据库的结构
SHOW CREATE DATABASE 创建的库名
- 查看指定数据库下保存的数据表
SHOW TABLES FROM mysql;
修改数据库(一般用不上,除非用新表)
更改数据库字符集
ALTER DATABASE 修改库名 CHARACTER SET ‘utf8’
删除数据库
方式一:
代码运行 例:DROP DATABASE 库名;
方式二::如果要删除的数据库存在,则删除成功,如果不存在,则默默结束,不会报错(推荐使用)
代码运行 例:DROP DATABASE IF EXISTS 库名;
创建数据表 CREATE TABLE IF NOT EXIDTD
方式一:(白手起家的创建方式)
代码运行 例:CREATE TABLE IF NOT EXIDTD myempl(//需要用户具备创建表的权限
Id INT,
emp_name VARCHAR(15),//使用VARCHAR来定义字符串,必须在使用VARCHAR时指明其长度
hire_data DATE
)
查看表结构
DESC myempl;
//如果创建表时没有指明使用的字符集,则默认使用表所在的数据库的字符集
查看创建表的语句结构
SHOW CREATE TABLE myempl
查看表数据
SELECT * FROM myempl
方式二:基于现有的表(就是复制查询的那个表的)
CREATE TABLE myemp2
AS
SELECT employee_id,last_name,salary
FROM employees;
修改表-àALTER TABLE
- 添加一个字段 ADD
ALTER TABLE myempl
ADD salay DOUBLE(10,2) //默认添加到表中的最后一个字段的位置
ALTER TABLE myempl
ADD phone_number VARCHAR(20) FIRST;
ALTER TABLE myempl
ADD email VARCHAR(45) AFTER emo_name
- 修改一个字段:数据类型,长度,默认值(略) MODIFY
ALTER TABLE myempl
MODIFY emp_name VARCHAR(25);
ALTER TABLE myempl
MODIFY emp_name VARCHAR(35) DEFAULT(这个就是修改的那个列名) ‘aaa’;
- 重命名一个字段 CHANGE
ALTER TABLE myempl
CHANGE salary(所要修改的旧名字) monthly_salary(新名字) DOUBLE(10,2)
ALTER TABLE myempl
CHANGE email my_email VARCHAR(50)(后面这个是修改范围的)
//在修改重命名字段的那个同时,是可以进行其他的范围类修改的
- 删除字段 DROP COLUMN
ALTER TABLE myempl
DROP COLUMN my_email;
重命名 RENAME TABLE
方式一:(推荐使用)
RENAME TABLE myempl
TO myempl1
方式二:
ALTER TABLE myempl2
RENAME TO myempl1;
删除表 DROP TABLE IF EXISTS
//不光将表结构删除掉,同时表中数据也删除掉,释放表空间
DROP TABLE IF EXISTS myemp2;
清空表 TRUNCATE TABLE
//清空表,表示清空表中所有的数据,但是表结构保留
TRUNCATE TABLE employees_copy
TRUNCATE TABLE和 DELETE FROM的区别
相同点:都可以实现对表中所有数据的删除,同时保留表的结构
不同点: TRUNCATE TABLE:执行操作后,不可实现回滚
DELETE FROM: 操作执行后,可以实现回滚·
//回滚使用ROLLBACK
数据处理 增删改
建议:在进行数据的增删改查时记得提前对数据进行查询好在数据最后确定是否完成需求的修改,还有就是在修改数据前对原有数据先提前进行保存,以防止修改错误所带来的不便
添加数据
方式一:一条一条的添加数据
1.代码运行 例:INSERT INTO 表名
VALUES (添加的数据) //一定要按照声明的字段的先后顺序添加
2.代码运行 例:INSERT INTO 表名(定义添加字段的列名) !!推荐使用
VALUES (添加的数据) //上面指明了添加的字段,所以下面可不去注意字段的先后顺序,没有进行赋值的字段值为null
3.代码运行 例:INSERT INTO 表名
VALUES (添加的数据)
(添加的数据)
(添加的数据)
//一次添加多条数据,在每一条数据后加 逗号,结尾最后一个加 分号
方式二:将查询结果插入表中
//查询的字段一定要与添加到的表的字段一一对应,要添加的数据字段的长度不能低于查询的字段长度,如果低于,则存在添加不成功的风险
先查询再用:INSERT INTO 表名(定义添加字段的列名)进行添加
更新数据(或修改数据)
代码运行 例:UPDATE……SET…….WHERE……
//主要就是在SET中写好想要修改的样子,在where中写要修改的字段
//修改数据时,是可能存在修改后不成功的,原因可能是由于约束的影响造成的
删除数据
代码运行 例:DELETE FROM …..WHERE…….
//删除数据也是可能存在删除失败的情况,同样也有可能由于约束的影响造成的
多种条件过滤 SELECT NAME AS 查询的列名 CASE WHEN 条件 THEN 标记 最后用END结束 END 是标记存在那个列的列头名
代码运行 例:
SELECT NAME AS “书名”,num AS “库存”, CASE WHEN num>30 THEN ‘销售’
WHEN num>0 AND num<10 THEN ‘畅销’
WHEN num=0 THEN ‘无货’
ELSE ‘正常’
END “正常状态”
小结:DML操作默认情况下,执行结束后都会自动提交数据,
如果希望执行完以后不自动提交数据,则需要使用SET autocommit=FALSE
MYSQL8的新特性:计算列
计算列
代码运行 例:CREATE TABLE test1
a INT,
b INT,
c INT GENERATED ALWAYS AS (a+b) VIRTUAL,
MYSQL数据类型(东西太多,使用时先查询吧,下面只是记录重要的部分)
!!!个人觉得数据类型好像就是用于数据的添加
关于属性:CHARACTER SET 字符集(用于创建表、库、字段指定字符集的时候使用)
//字符集的默认是循序递进,未特殊声明会遵循上一级的默认
ZEROFULL //显示宽度,放于定义的数据类型之后,当定义值不足时会用零进行填充
UNSIGNED //无符号
//浮点型中超出小数的范围进行四舍五入
//DECIMAL数据类型的精准性极强,适用于在进行需要准确性极强的项目中
//使用TIMESTAMP存储的同一个时间值在不同的时区查询时会显示不同的时间
//TEXT文本类型,可以存较大的文本字段,搜索速度较慢,因此如果不是特别大的内容,建议使用CHAR,VARCHAR来代替,还有TEXT类型不用加默认值,加了也没用。而且text和blob类型的数据删除后容易导致‘空洞,使得文件碎片比较多,所以频繁使用的表不建议包含TEXT类型字段,建议单独分出去,单独用一个表’
//枚举元素添加忽略大小写,其可以使用索引进行枚举元素的调用,而且并没有限定非空,空值一样可以添加
二进制字符型类型
BINARY 与 VARBINARY 的区别:前者固定长度后者可变长度
小结:
- 任何字段如果为非负数,必须是UNSIGNED
- 小数类型为DECIMAL,禁止使用FLOAT和DOUBLE 因为在存储的时候,FLOAT和DOUBLE都存在精度损失的问题,很可能比较值的时候,得到不正确的结果,如果存储的数值范围超过DECIMAL的范围,建议将数据拆分为整数和小数分开存储
- 如果存储的字符串长度几乎相等,使用CHAR定长字符串类型
VARCHAR是可变长字符串,不预先分配存储空间,长度不要超过5000,如果存储长度大于此值,定义字段类型为TEXT,独立出来一张表,用主键来对应,避免影响其他字段索引效率
约束(constraint)
为了保证数据的完整性,所以需要约束,其就是对表中字段的限制
约束的分类
角度一:约束的字段的个数
单列约束 vs 多列约束
角度二:约束的作用范围
列级约束:将此约束声明在对应字段的后面
表级约束:在表中所有的字段都声明完,在所有的字段的后面声明的约束
角度三:约束的作用(或功能)
- not null(非空约束) //限定某个字段/列的值不能为空
- unique(唯一性约束) //确定其是唯一
//创建唯一约束的时候,如果不给唯一约束命名,就默认和列名相同,可以声明在其所字段添加null值,而且可以多次添加
- primary key(主键约束)//非空且唯一,用于唯一标识表中的一行记录
//一个表中最多只能有一个主键约束
- foreign key(外键约束)//限定某个表的某个字段的引用完整性
//对于外键约束,最好采用:‘ON UPDATE CASCADE ON DELETE RESTRICT 的方式
- check(检查约束)//检查某个字段的值是否符合xx要求,一般指的是值的范围
//MYSQL5.7是不支持的但8.0支持
- default(默认值约束)//设置默认值
添加约束
CREATE TABLE时添加约束
ALTER TABLE 时增加约束、删除约束
查看表中的约束
SELECT * FROM information_schema.table_constraints
WHERE table_name=’表名称’;
自增长列:AUTO_INCREMENT主要用于主键
当我们向主键的字段添加0或者null时,实际上会自动的往上添加指定的值
开发中,一旦主键作用的字段上声明有AUTO_INCREMENT,则我们在添加数据时,就不要给主键对应的字段进行赋值了
视图
- 视图,可以看做是一个虚拟表,本身是不存储数据的,视图本质,就可以看做是存储起来的SELECT语句
- 视图中SELECT语句中涉及到的表,称为基表
- 针对视图做DML操作,会影响到对应的基表中的数据,反之亦然
- 视图本身的删除,不会导致基表中数据的删除
- 视图的应用场景:针对于小型项目,不推荐使用视图,针对大型项目,可以考虑使用视图
- 视图的优点:简化查询,控制数据的访问,操作简单,数据安全,适应灵活多变的需求,能够分解复杂的查询逻辑
- 视图不足:如果实际数据表的结构变更了,我们就需要及时对相关的视图进行相应的维护,实际项目中,如果视图过多的话,会导致数据库维护成本很高
创建视图
在CREATE OR REPLACE VIEW语句中嵌入子查询(其实就是下面写查询表上面写CREATE VIEW OR REPLACE AS即可)
查看视图
查看数据库的表对象、视图对象
SHOW TABLES
查看视图的结构
DESCRIBE 视图名
查看视图的属性信息
SHOW TABLE STATUS LIKE 视图名
查看视图的详细定义信息
SHOW CREATE VIEW 视图名
更新视图
更新视图中的数据,会导致表中数据修改,同理,更新表中的数据,也会导致视图中的数据进行了修改,删除也是一样的 不可以更新删除视图
删除视图
DROP VIEW
存储过程与函数
创建存储过程 CREATE PROCEDURE
代码运行: 例: DELIMITERL $
CREATE PROCEDURE 存储名
BEGIN
SELECT * FROM employees
END $
DELIMITERL;
调用
CALL 存储名()
返回值
理解为有零个或多个
应用场景
一般用于更新
存储函数 CREATE FUNCTION
调用
SELECT 函数()
返回值
只能有一个
应用场景
一般用于查询结果为一个值并返回时
//存储函数可以放在查询语句中使用,存储过程不行
存储过程、存储函数的查看
- SHOW CREATE 存储过程或函数
- SHOW 存储过程或函数 STATUS
存储过程和存储函数的修改
代码运行 例:ALTER PROCEDURE show_max_salary
SQL SECURITY INVOKER
COMMENT ‘查询最高工资
存储过程、函数删除
DROP FUNCTION IF EXISTS count_by_id;’
优点
存储过程可以一次编写多次使用、可以减少开发工作量、存储过程的安全性强、可以减少网络的传输量、良好的封装性
缺点
可移植性差、调试困难、存储过程的版本管理很困难、它不适合高并发的场景
变量、流程控制与游标
变量
变量分为系统变量(全局系统变量、会话系统变量)以及用户自定义变量(会话用户变量、局部变量)
查询系统变量
查询全局系统变量
SHOW GLOBAL VARIABLES;
查询会话系统变量
SHOW SESSION VARIABLES
默认查询的是会话系统变量
SHOW VARIABLES
查询部分系统变量
SHOW GLOBAL VARIABLES LIKE ‘admin_%’
SHOW VARIABLES LIKE ‘character_%’
查询指定的系统变量
SELECT @@global.变量名
查看指定的会话变量的值
SELECT @@session.变量名 或者 SELECT @@变量名
修改系统变量的值
为某个系统变量赋值(全局系统变量)
SET @@global.变量名=变量值 或者 SET GLOBAL 变量名=变量值
//此修改只是针对当前的数据库实例是有效的,一旦重启mysql服务,就失效了
为某个会话变量赋值(会话系统变量)
SET @@session.变量名=变量值 或者 SET SESSION 变量名=变量值
//此修改只是针对当前的会话是有效的,一旦结束会话,重新建立起新的会话,就失效了
用户变量
会话用户变量:使用@开头,作用域为当前会话
局部变量:只能使用在存储过程和存储函数中的
会话用户变量的定义
变量的声明和赋值
- SET @用户变量=值
- SET @用户变量:=值
- SELECT @用户变量:=表达式[FROM等子句]
- SELECT 表达式 INTO @用户变量[FROM 等子句]
使用
SELECT @变量名
局部变量
局部变量必须使用DECLARE声明,并使用在BEGIN…END中(使用在存储过程、函数中),而且DECLARE的方式声明的局部变量必须声明在BEGIN中的首行位置
声明格式
DECLARE 变量名 类型[default 值] //如果没有DEFAULT子句,初始值为NULL
变量赋值
- SET 变量名=值
- SET 变量名:=值
- SELECT 字段名或表达式INTO 变量名 FROM 表
使用
SELECT 局部变量名
定义条件与处理程序
定义处理程序
DECLARE 处理方式 HANDLER FOR 错误类型 处理语句
处理方式
- CONTINUE:表示遇见错误不处理,继续执行
- EXIT:表示遇见错误马上退出
- UNDO:表示遇见错误后撤回之前的操作,MYSQL中暂时不支持这样的操作
错误类型
- SQLSTATE ‘字符串错误码’ :表示长度为5的sqlstate_value类型的错误代码
- MYSQL_error_code:匹配数据类型错误代码
- 错误名称:表示DECLARE…CONDITION定义的错误条件名称
- SQLWARNING:匹配所有以01开头的SQLSTATE错误代码
- NOT FOUND:匹配所有以02开头的SQLSTATE错误代码
- SQLEXCEPTION: 匹配所有没有被SQLWARNING或NOT FOUND捕获的SQLSTATE错误代码
处理语句
如果出现上述的条件之一,则采用对应的处理方式,并执行指定的处理语句,语句可以像“SET变量=值”这样的简单语句,也可以是使用BEGIN…END编写的复合语句
流程控制
- 顺序结构:程序从上往下依次执行
- 分支结构:程序按条件进行选择执行,从两条或多条路径中选择一条执行
- 循序结构:程序满足一定条件下,重复执行一组语句
针对MYSQL的流程控制语句主要有三类。 //注意:只能用于存储程序
- 条件判断语句:IF语句和CASE语句
- 循环语句:LOOP,WHILE和REPEAT语句
- 跳转语句:ITERATE和LEAVE语句
IF语句的语法结构
IF 表达式1 THEN 操作1
[ELSEIF 表达式2 THEN 操作2]… ….
[ELSE 操作N]
END IF
根据表达式的结果为TRUE或FALSE执行相应的语句,这里【】中的内容是可选的
特点:1不同的表达式对应不同的操作2使用在begin end中
CASE语句的语法结构
情况一:类似于switch
CASE 表达式
WHEN 值1 THEN 结果1或语句1(如果是语句,需要加分号)
WHEN 值2 THEN 结果2或语句2(如果是语句,需要加分号)
…
ELSE 结果n或语句n(如果是语句,需要加分号)
END [case](如果是放在begin end中需要加上case,如果放在select后面不需要)
情况二:类似于多重if
CASE
WHEN 值1 THEN 结果1或语句1(如果是语句,需要加分号)
WHEN 值2 THEN 结果2或语句2(如果是语句,需要加分号)
…
ELSE 结果n或语句n(如果是语句,需要加分号)
END [case](如果是放在begin end中需要加上case,如果放在select后面不需要)
LOOP语句的基本格式
[loop_label:] LOOP
循环执行的语句
END LOOP [loop_label]
//其中,loop_label表示LOOP语句的标注名称,该参数可以省略
WHILE语句的基本格式
[while_lable:] WHILE 循环条件 DO
循环体
END WHILE [while_lable];
REPEAT语句的基本格式
[repeat_lable:] REPEAT
循环体的语句
UNTIL 结束循环的条件表达式
END REPEAT [repeat_label]
三种循环结构对比
- 这三种循环都可以省略名称,但如果循环中添加了循环控制语句(LEAVE或ITERATE)则必须添加名称
- LOOP:一般用于实现简单的死循环
WHILE:先判断后执行
REPEAT:先执行后判断,无条件至少执行一次
循环结构中必备的四个条件:1初始化条件2循环条件3循环体4迭代条件
游标 //就是指定某个条件
游标的使用过程
1声明游标
2打开游标
3使用游标(从游标中获取数据)
4关闭游标
小结
游标是MySQL的一个重要的功能,为逐步读取结果集中的数据,提供了完美的解决方案,跟在应用层面实现相同的功能相比,游标可以在存储程序中使用,效率高,程序也更加简洁。
但同时也会带来一些性能问题,比如在使用游标的过程中,会对数据行进行加锁,这样在业务并发量大的时候,不仅会影响业务之间的效率,还会消耗系统资源,造成内存不足,这是因为游标是在内容中进行的处理
建议:养成用完之后就关闭的习惯,这样才能提高系统的整体效率
//MySQL8.0版本新增SET PERSIST命令 全局变量的持久化
触发器
触发器简介
触发器是由事件来触发的,这些事件包括INSERT、UPDATE、DELETE事件,所谓事件就是指用户的动作或者触发某项行为,如果定义了触发程序,当数据库执行这些语句的时候,就相当于事件发生了,就会自动激发触发器执行相应的操作
当数据表中的数据执行插入、更新和删除操作,需要自动执行一些数据库逻辑时,可以使用触发器来实现
触发器创建
语法结构
CREATE TRIGGER 触发器名称
{REFORE | AFTER} {INSERT | UPDATE |DELETE} ON 表名
FOR EACH ROW
触发器执行的语句块
说明
- 表名:表示触发器监控的对象
- BEFORE | AFTER :表示触发的时间,BEFORE表示在事件之前触发;AFTER表示在事件之后触发
- INSERT | UPDATE | DELETE:表示触发的事件
INSERT 表示插入记录时触发
UPDATE 表示更新记录时触发
DELETE 表示删除记录时触发
- 触发器执行的语句块:可以是单条SQL语句,也可以是由BEGIN…END结构组成的复合语句块
查看触发器
方法一:SHOW TRIGGERS\G
方法二:SHOW CREATE TRIGGER 触发器名
方法三:SELECT * FROM information_schema.TRIGGERS
删除触发器
DROP TRIGGER IF EXISTS 触发器名称;
触发器的优缺点
优点
- 触发器可以确保数据的完整性
- 触发器可以帮我们记录操作日志
- 触发器还可以用在操作数据前,对数据进行合法性检查
缺点
- 触发器最大的一个问题就是可读性差
- 相关数据的变更,可能会导致触发器的出错
注意点
注意。如果在子表中定义了外键约束,并且外键指定了ON UPDATE/DELETE CASCADE/SET NULL子句,此时修改父表被引用的键值或删除父表被引用的记录行时,也会引起子表的修改和删除操作,此时基于子表的UPDATE和DELETE语句定义的触发器并不会被激活
MYSQL8.0新增特性
窗口函数
公用表表达式
公用表表达式(或通用表表达式)简称为CTE, CTE是一个命名的临时结果集,作用范围是当前语句,CTE可以理解成一个可以复用的子查询,当然跟子查询还是有点区别的,CTE可以引用其他CTE,但是子查询不能引用其他的子查询,所以可以考虑代替子查询
依据语法结构和执行方式不同,公用表表达式分为普通公用表表达式和递归公用表表达式2种
普通公用表表达式的语法结构
WITH CTE名称
AS (子查询)
SELECT | DELETE | UPDATE 语句;
递归公用表表达式的语法结构
WITH RECURSIVE
CTE名称 AS (子查询)
SELECT | DELETE | UPDATE 语句;