MySQL基础篇-12-变量、流程控制和游标
变量
在 MySQL 数据库中,变量分为系统变量以及用户自定义变量 。
系统变量
变量由系统定义,不是用户定义,属于服务器层面。启动 MySQL 服务,生成 MySQL 服务实例期间, MySQL 将为 MySQL 服务器内存中的系统变量赋值,这些系统变量定义了当前 MySQL 服务实例的属性、特征。
系统变量分类
系统变量分为全局系统变量(需要添加 global 关键字)以及会话系统变量(需要添加 session 关键字),有时也把全局系统变量简称为全局变量,有时也把会话系统变量称为 local 变量。如果不写,默认会话级别。静态变量(在 MySQL 服务实例运行期间它们的值不能使用 set 动态修改)属于特殊的全局系统变量。
每一个 MySQL 客户机成功连接 MySQL 服务器后,都会产生与之对应的会话。会话期间,MySQL 服务实例会在 MySQL 服务器内存中生成与该会话对应的会话系统变量,这些会话系统变量的初始值是全局系统变量值的复制。如下图:
- 全局系统变量针对于所有会话(连接)有效,但不能跨重启
- 会话 1 对某个全局系统变量值的修改会导致会话 2 中同一个全局系统变量值的修改
查看系统变量
查看所有或部分系统变量
1 | -- 查看所有全局变量 |
查看指定系统变量
作为 MySQL 编码规范,MySQL 中的系统变量以 两个 @
开头,其中 @@global
仅用于标记全局系统变量,@@session
仅用于标记会话系统变量。@@
首先标记会话系统变量,如果会话系统变量不存在, 则标记全局系统变量。
1 | -- 查看指定的系统变量的值 |
修改系统变量的值
- 方式1:修改 MySQL 配置文件 ,继而修改 MySQL 系统变量的值(该方法需要重启 MySQL 服务)
- 方式2:在 MySQL 服务运行期间,使用
set
命令重新设置系统变量的值
1 | -- 为某个系统变量赋值 |
用户变量
用户变量分类
用户变量是用户自己定义的,作为 MySQL 编码规范,MySQL 中的用户变量以一个 @
开头。根据作用范围不同,又分为会话用户变量和局部变量。
- 会话用户变量:作用域和会话变量一样,只对当前连接会话有效
- 局部变量:只在
BEGIN
和END
语句块中有效。局部变量只能在存储过程和函数中使用。
会话用户变量
变量的定义
1 | -- 方式1:“=”或“:=” |
查看用户变量的值 (查看、比较、运算等)
1 | SELECT @用户变量 |
局部变量
- 定义:可以使用
DECLARE
语句定义一个局部变量 - 作用域:仅仅在定义它的
BEGIN ... END
中有效 - 位置:只能放在
BEGIN ... END
中,而且只能放在第一句
1 | BEGIN |
定义变量
1 | DECLARE 变量名 类型 [default 值]; # 如果没有DEFAULT子句,初始值为NULL |
变量赋值
1 | -- 一般用于赋简单的值 |
使用变量 (查看、比较、运算等)
1 | SELECT 局部变量名; |
1. 声明局部变量,并分别赋值为employees表中employee_id为102的last_name和salary
1 | DELIMITER // |
2. 声明两个变量,求和并打印 (分别使用会话用户变量、局部变量的方式实现)
1 | -- 方式1:使用用户变量 |
3. 创建存储过程“different_salary”查询某员工和他领导的薪资差距,并用IN参数emp_id接收员工 id,用OUT参数dif_salary输出薪资差距结果。
1 | -- 声明 |
用户变量和局部变量对比
作用域 | 定义位置 | 语法 | |
---|---|---|---|
会话用户变量 | 当前会话 | 会话的任何地方 | 加@符号,不用指定类型 |
局部变量 | 定义它的BEGIN END中 | BEGIN END的第一句话 | 一般不用加@,需要指定类型 |
定义条件
定义条件就是给 MySQL 中的错误码命名,这有助于存储的程序代码更清晰。它将一个错误名字和指定的错误条件关联起来。这个名字可以随后被用在定义处理程序的 DECLARE HANDLER
语句中。
1 | DECLARE 错误名称 CONDITION FOR 错误码(或错误条件) |
MySQL_error_code 和 sqlstate_value 都可以表示 MySQL 的错误。
MySQL_error_code 是数值类型错误代码
sqlstate_value 是长度为 5 的字符串类型错误代码。
定义处理程序
可以为 SQL 执行过程中发生的某种类型的错误定义特殊的处理程序
1 | DECLARE 处理方式 HANDLER FOR 错误类型 处理语句 |
处理方式:处理方式有 3 个取值:CONTINUE、EXIT、UNDO
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 编写的复合语句。
1 | -- 方法1:捕获sqlstate_value |
流程控制
分支结构 IF
1 | IF 表达式1 THEN 操作1 |
分支结构 CASE
1 | -- 情况一:类似于switch |
循环结构 LOOP
1 | -- 其中,loop_label表示LOOP语句的标注名称,该参数可以省略。 |
1 | DECLARE id INT DEFAULT 0; |
循环结构 WHILE
1 | -- while_label为WHILE语句的标注名称;如果循环条件结果为真,WHILE语句内的语句或语句群被执行,直至循环条件为假,退出循环。 |
循环结构 REPEAT
REPEAT 语句创建一个带条件判断的循环过程。与 WHILE 循环不同的是,REPEAT 循环首先会执行一次循环,然后在 UNTIL 中进行表达式的判断,如果满足条件就退出,即 END REPEAT;如果条件不满足,则会就继续执行循环,直到满足退出条件为止。
1 | -- repeat_label为REPEAT语句的标注名称,该参数可以省略;REPEAT语句内的语句或语句群被重复,直至expr_condition为真。 |
跳转结构 LEAVE
LEAVE 语句:可以用在循环语句内,或者以 BEGIN 和 END 包裹起来的程序体内,表示跳出循环或者跳出 程序体的操作 (类似 break)
1 | LEAVE 标记名 |
跳转结构 ITERATE
ITERATE 语句:只能用在循环语句(LOOP、REPEAT 和 WHILE 语句)内,表示重新开始循环,将执行顺序 转到语句段开头处。(类似 continue)
1 | ITERATE label |
游标
在 SQL 中,游标是一种临时的数据库对象,可以指向存储在数据库表中的数据行指针。这里游标充当指针的作用 ,可以通过操作游标来对数据行进行操作。MySQL 中游标可以在存储过程和函数中使用。
游标必须在声明处理程序之前被声明,并且变量和条件还必须在声明游标或处理程序之前被声明。 如果我们想要使用游标,一般需要经历四个步骤。
第一步,声明游标
1 | DECLARE cursor_name CURSOR FOR select_statement; |
第二步,打开游标
1 | OPEN cursor_name |
当我们定义好游标之后,如果想要使用游标,必须先打开游标。打开游标的时候 SELECT 语句的查询结果集就会送到游标工作区,为后面游标的 逐条读取 结果集中的记录做准备。
第三步,使用游标(从游标中取得数据)
1 | FETCH cursor_name INTO var_name [, var_name] ... |
使用 cursor_name 这个游标来读取当前行,并且将数据保存到 var_name 这个变量中,游 标指针指到下一行。如果游标读取的数据行有多个列名,则在 INTO 关键字后面赋值给多个变量名即可。
注意:var_name 必须在声明游标之前就定义好。
第四步,关闭游标
1 | CLOSE cursor_name |
案例
创建存储过程 get_count_by_limit_total_salary()
,声明 IN 参数 limit_total_salary
,DOUBLE 类型;声明 OUT 参数 total_count
,INT 类型。函数的功能可以实现累加薪资最高的几个员工的薪资值,直到薪资总和达到 limit_total_salary
参数的值,返回累加的人数给 total_count
。
1 | DELIMITER // |