黑马MySQL数据库从入门到精通-基础篇 2
黑马MySQL数据库从入门到精通-基础篇 2
智汇君游标
1 | 游标(CURSOR)是用来存储查询结果集的数据类型,在存储过程和函数中可以使用游标对结果集进行循环的处理。游标的使用包括游标的声明、OPEN、FETCH和 CLOSE,其语法分别如下。 |
用法
1 | 声明游标 |
案例1
1 | 执行创建存储过程命令报错,声明变量和声明游标的顺序有要求 |
1 | 上面的报错是因为执行存储过程后,当游标里的数据遍历完成后,由于是死循环当无数据时也执行,导致报错 |
异常处理程序
1 | 上图是对前面的案例的改进 |
案例2
1 | 创建存储过程,里面使用游标,对每一行进行数据修改 |
案例3
1 | 创建存储过程,里面使用游标,对score小于60的进行删除 |
案例4 异常处理程序
1 | DELIMITER // |
案例5 带输入参数 in
1 | create procedure sp1(in p int) |
案例6 带输出参数 out
1 | create procedure sp2(out p int) |
案例7 带输入和输出参数 in out
1 | create procedure sp3(in p1 int , out p2 int) |
案例8 inout
1 | drop procedure if exists sp4 // |
案例9 事务 异常处理程序
1 | #存储过程异常处理 |
案例10 复杂案例 异常处理 回滚
1 | #编写取消订单的存储过程 |
案例
1 | DELIMITER // |
案例
1 | DELIMITER // |
存储过程
介绍
1 | 存储过程是事先经过编译并存储在数据库中的一段SQL语句的集合,调用存储过程可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的。存储过程思想上很简单,就是数据库SQL 语言层面的代码封装与重用。 |
特点
1 | 封装,复用,更加安全。 |
基本语法
创建
1 | create procedure pro_name() |
变量
1 | 声明局部变量:要在存储过程中声明一个变量,可以使用DECLARE语句 |
1 | 赋值:要为变量分配一个值,可以使用SET语句,或者使用SELECT INTO语句将查询的结果分配给一个变量 |
1 | 变量范围(作用域) |
参数
1 | 在MySQL中,参数有三种模式:IN,OUT或INOUT。 |
delimiter
1 | mysql中的默认的语句结束符为分号;但是例如我们需要在命令行输入较复杂的语句时(如存储过程,存储函数等),可能包含多行语句或者语句中包含分号,那么mysql在遇到第一个分号时就会执行。delimiter就是用于修改语句结束符,使得在正确编写完sql语句后再执行 |
1 | DELIMITER $$ |
1 | mysql> delimiter // |
1 | delimiter // |
调用
1 | call pro_name(); |
查看
1 | SELECT * FROM INFORMATON_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA='xxx'; -查询指定数库的存储过程及状态信息 |
删除
1 | DROP PROCEDURE [IF EXIST5] 存储过程名称; |
注意
1 | 注意: 在命令行中,执行创建存储过程的SQL时, |
存储过程异常处理handler
1 | 01)当sql出现异常的时候跳出存储过程并设置值为xxx |
1 | 注意:异常情况可以写异常错误码、异常别名或SQLSTATE码。 |
1 | handler_action |
Prepare、execute、deallocate
语法
1 | PREPARE stmt from '你的sql语句'; // PREPARE msql FROM @MyQuery; 变量存放sql |
1 | PREPARE语句准备好一条SQL语句,并分配给这条SQL语句一个名字供之后调用。准备好的SQL语句通过EXECUTE命令执行,通过DEALLOCATE PREPARE命令释放掉。 |
1 | 使用预处理语句时 要使用的是 【用户变量】(使用SET @xxx = xxxx 方式声明 ) 不同于局部变量 (DECLARE 定义的变量)。 |
优点
1 | 他还可以在存储过程中动态的拼接表名,字段名,来达到动态查询的效果 |
疑惑解答
1 | 疑惑解答: |
案例
1 | delimiter // |
1 | delimiter // |
1 | # 第一种使用方式: 使用USING传入参数 |
1 | SET @TargetTableName = CONCAT('xxxxxxx','_',DATE_FORMAT(NOW(),'%Y')); --yourtablename_2022你的分表格式,前缀加日期 |
存储函数
1 | 存储函数是有返回值的存储过程,存储函数的参数只能是IN类型的。 |
语法
1 | CREATE FUNCTION 存储函数名称([参数列表]) |
与存储过程的区别
1 | 存储函数只能返回一个值,而存储过程可以返回零个或多个值 |
1 | 报错是因为版本问题 |
触发器
介绍
1 | 触发器是与表有关的数据库对象,指在insert/update/delete之前或之后,触发并执行触发器中定义的SQL语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性,日志记录,数据校验等操作。 |
语法
1 | CREATE TRIGGER trigger_name |
1 | SHOW TRIGGERS; --当前数据库触发器 |
1 | DROP TRIGGER.[schema_name.]trigger_name; |
insert类型
insert插入之后在其它表插入相关信息
1 | DELIMITER // |
1 | AFTER INSERT 特别适合这种状态变更的关联写入操作。比如开户、暂停、注销等各类状态变更。 |
insert插入之前检查数据是否符合规范
1 | DELIMITER // |
update类型
before update
1 | BEFORE UPDATE触发器与BEFORE INSERT 触发器非常类似,我们可以使用BEFORE UPDATE 触发器在更新数据之前,先做一次业务逻辑检测,避免发生误操作。 |
1 | DELIMITER // |
after update
1 | AFTER UPDATE 多用于 log 记录,在管理系统多操作者使用的环境中,管理员需要设置操作 log 记录,以便在出问题时,可以查看操作者对表编辑的操作,可追根溯源。 |
1 | 下面的就是前面说的行级触发器问题了,影响多少行就触发多少次 |
1 | 触发器将监测用户 ID 、更新前的销售总额、更新后的销售总额、操作者 ID、修改时间等信息,作为 log 存入 audit_log 表中。 |
delete类型
after delete
1 | AFTER DELETE触发器的另一个用途是在删除主表中的数据后,与这个主表关联的数据,一起自动删除。 |
before delete
1 | 这些类型的触发器通常用于在不同的相关表上强制执行参照完整性。 |
1 | 例如:sales 表通过customer_id 与customers表相关联。如果操作者删除了customers 表中的一条数据,那么 sales 表中某些数据就失去了关联线索。 |
1 | 不过有时候,我们需要删除主数据后,再让系统自动帮我们删除与之相关联的其他所有数据。这时,我们就要用到 AFTER DELETE 这个触发器了。 |
变量
系统变量
会话变量
1 | 会话变量是由系统提供的,只在当前会话(连接)中有效。 |
查看
1 | # 查看所有会话变量 |
设置
1 | SET [SESSION|GLOBAL] 系统变量名=值; |
1 | 注意: |
全局变量
1 | 全局变量由系统提供,整个MySQL服务器内有效。 |
1 | # 查看全局变量中变量名有char的记录 |
用户自定义变量
1 | 用户变量不用提前声明,使用即为声明。其作用域为当前连接(会话)。 |
赋值
1 | SET @var_name=expr[,@var_name=expr] ...; |
1 | mysql中没有==比较运算符,赋值和比较运算符都是= |
使用
1 | select @var_name; |
注意
1 | 注意: |
案例
1 | delimiter // |
1 | delimiter // |
1 | delimiter // |
局部变量
1 | 局部变量是根据需要定义的在局部生效的变量,访问之前,需要DECLARE声明。可用作存储过程内的局部变量,局部变量的范围是在其内声明的BEGIN...END块 |
声明
1 | DECLARE 变量名 变量类型[DEFAULT ...]; |
赋值
1 | SET 变量名=值 |
IF条件判断
语法
1 | IF 条件1 THEN |
参数
用法
1 | CREATE PROCEDURE 存储过程名称([IN/OUT/INOUT 参数名 参数类型]) |
case
语法一
1 | CASE case_value |
语法二
1 | CASE |
循环
1 | leave和iterate与break和continue类似 |
while
1 | [别名] WHILE 条件 DO |
1 | delimiter // |
repeat
1 | repeat循环类似Java中的do while循环 |
1 | [别名:] REPEAT |
1 | delimiter // |
loop
1 | loop为死循环,需要手动退出循环,我们可以使用 leave 来退出循环 |
1 | LOOP 实现简单的循环,如果不在SQL逻辑中增加退出循环的条件,可以用其来实现简单的死循环。LOOP可以配合一下两个语句使用: |
1 | [别名:] LOOP |
1 | delimiter // |
1 | delimiter // |
视图
1 | 视图是一个虚拟表,其内容由查询定义。数据库中只存放了视图的定义,而并没有存放视图中的数据,这些数据存放在原来的表中。使用视图查询数据时,数据库系统会从原来的表中取出对应的数据。因此,视图中的数据是依赖于原来的表中的数据的。一旦表中的数据发生改变,显示在视图中的数据也会发生改变。同样对视图的更新,会影响到原来表的数据。 |
1 | 安全原因,视图可以隐藏一些数据,例如,员工信息表,可以用视图只显示姓名、工龄、地址,而不显示社会保险号和工资数等。这个视图就像一个窗口,从中只能看到你想看的数据列。 |
作用
优点
1 | 1.使操作简单化 |
缺点
1 | 在实际数据表的基础上创建视图,那么如果实际数据表的结构变更了,我们就需要及时对相关的视图进行相应的维护。特别是嵌套的视图(就是在视图的基础上创建视图),维护会变得比较复杂, 可读性不好,容易变成系统的潜在隐患。因为创建视图的SQL查询可能会对字段重命名,也可能包含复杂的逻辑,这些都会增加维护的成本。实际项目中,如果视图过多,会导致数据库维护成本的问题。 |
语法
1 | 创建视图是指在已经存在的数据库表上建立视图。视图可以建立在一张表中,也可以建立在多张表中 |
1 | CREATE [OR REPLACE] [ALGORITHM={UNDEFINED|MERGE|TEMPTABLE}] |
创建
1 | 针对别名的处理,可以在创建视图的子查询中指定对应的别名 |
1 | 也可以在创建视图的视图名称后添加对应的别名字段 |
1 | 可以基于视图创建视图 |
通过视图变更数据
插入
1 | 首先v_order是很多张表连接得到的视图 |
WITH CHECK OPTION
1 | 如果在创建视图的时候制定了“WITH CHECK OPTION”,那么更新数据时不能插入或更新不符合视图限制条件的记录。 |
1 | create view v_price3000up |
删除
1 | DROP VIEW IF EXISTS view_student; |
注意
1 | -在定义视图的SELECT语句中包含了子查询,而子查询中引用了FROM后面的表,视图将不支持 INSERT、UPDATE、DELETE; |
临时表
1 | 在MySQL中,临时表是一种特殊的表,它用于在当前会话中存储临时数据集。这些表在会话结束时自动销毁,非常适合存储中间结果集或进行复杂查询时使用。 |
语法
1 | CREATE TEMPORARY TABLE temp_table_name ( |
1 | 也可以通过查询结果来创建临时表,这样可以直接将查询结果集存储在临时表中,而不需要单独插入数据。例如: |
注意
1 | 一旦临时表被创建,你就可以像使用普通表一样对其进行各种操作,包括插入、查询、修改和删除数据 |












































