MySQL变量、流程控制与游标

目录

1.变量

1.1系统变量

注:

1.2查看系统变量

查看所有全局变量:

1.3查看指定的全局系统变量的值:

1.4修改系统变量的值

1.5为某个系统变量赋值

1.6为某个会话变量赋值

2.用户变量

2.1会话用户变量

2.11变量的定义:

方式一:使用SET的方式

方式二:查询时使用INTO的方式

2.12查看用户变量的值(查看、比较、运算等)

 2.2局部变量

2.21定义

2.22位置

2.3定义条件与处理程序

2.4定义条件

2.5定义处理程序 

定义处理程序的几种方式 

3. 流程控制

3.1 分支结构之 IF

3.11IF 语句的语法结构:

3.12特点:

 举例:

3.2 分支结构之 CASE

3.21CASE 语句的语法结构1:

CASE 语句的语法结构2:

举例

 3.3 循环结构之LOOP

LOOP语句的基本格式

举例

3.4 循环结构之WHILE

语法:

举例 

3.5 循环结构之REPEAT

 REPEAT语句的基本格式

 举例

对比三种循环结构:

 3.6 跳转语句之LEAVE语句

基本格式

举例

3.7 跳转语句之ITERATE语句

 语句基本格式

举例

4. 游标

 4.1 什么是游标(或光标)

 4.2 使用游标步骤

第一步,声明游标

语法的基本形式:

第二步,打开游标

打开游标的语法:

第三步,使用游标(从游标中取得数据)

语法如下:

第四步,关闭游标

4.3 举例


1.变量

1.1系统变量

系统变量分为全局系统变量(需要添加global关键字)以及会话系统变量(需要添加session关键字)有时将全局系统变量简称为全局变量,将会话系统变量称为local变量。如果不写,默认会话级别。静态变量属于特殊的全局系统变量。

注:

全局系统变量针对于所有的会话(连接)有效,但不能跨重启。

会话系统变量仅针对于当前会话(连接)有效,会话期间,当前会话对某个会话系统变量值的修改,不会影响其他会话同一个会话系统变量的值。

会话1对某个全局变量值的修改会导致会话2中同一个全局变量值的修改。

1.2查看系统变量

查看所有全局变量:

SHOW GLOBAL VARIABLES [LIKE '……'];

查看所有会话变量:

SHOW SESSION VARIABLES [LIKE '……'];

SHOW VARIABLES;-- 默认会话级别

MySQL中的系统变量以两个@开头,其中@@global仅用于标记全局系统变量,@@session仅用于标记会话系统变量。@@后如果未跟global或session,@@会首先标记会话系统变量,如果会话系统变量不存在,则标记全局系统变量。

1.3查看指定的全局系统变量的值:

SELECT @@global.变量名;

查看指定的会话变量的值

SELECT @@session.变量名;

或者

SELECT @@变量名;

1.4修改系统变量的值

方式一:修改MySQL配置文件,继而修改MySQL系统变量的值(该方法需要重启MySQL服务)

方式二:在MySQL服务运行期间,使用SET命令重新设置系统变量的值。

1.5为某个系统变量赋值

SET @@global.变量名 = 变量值;

SET GLOBAL 变量名 = 变量值;

针对于当前的数据库实例有效,一旦重启MySQL服务就失效。

1.6为某个会话变量赋值

SET @@session.变量名 = 变量值;

SET SESSION 变量名 = 变量值;

注意:对当前会话有效

2.用户变量


用户变量是用户自己定义的,作为MySQL编码规范,MySQL中的用户变量以一个@开头。根据作用范围的不同,又分为会话用户变量和局部变量。

会话用户变量:作用域和会话变量一样,只对当前连接的会话有效。

局部变量:只在BEGIN和END语句中有效。局部变量只能在存储过程和存储函数中使用。

2.1会话用户变量

2.11变量的定义:

方式一:使用SET的方式
SET @用户变量 = 值;

SET @用户变量 := 值;

方式二:查询时使用INTO的方式
SELECT 表达式 INTO @用户变量 [FROM等子句];
SELECT @用户变量 :=表达式 [FROM等子句];

2.12查看用户变量的值(查看、比较、运算等)

SELECT @用户变量

SELECT @用户变量……

 
2.2局部变量

2.21定义

使用DECLARE语句定义一个局部变量。

作用域:只在BEGIN和END中间有效。

2.22位置

只能放在BEGIN和END中,且只能放在第一句。

BEGIN

声明局部变量

DECLARE 变量名 变量数据类型 [DEFAULT 变量默认值];

DECLARE 变量名,变量名,…… 变量数据类型 [变量默认值];

为局部变量赋值

SET 变量名 = 值;

SELECT 值 INTO 变量名 [FROM 子句];

查看局部变量的值

SELECT 变量名,变量名,……;

END

注:局部变量如果没有DEFAULT子句,初始值为NULL。

2.3定义条件与处理程序

        定义条件是事先定义程序执行过程中可能遇到的问题,处理程序定义了在遇到问题时的处理方式,并且保证存储过程或存储函数在遇到警告时能继续执行。

2.4定义条件

定义条件就是给MySQL中的错误码命名,有助于存储的程序代码更清晰。定义条件将一个错误名字和指定的错误条件关联起来。这个名字可以随后被用在处理程序的DECLARE HANDLER语句中。

定义条件使用DECLARE语句,语法格式如下:

DECLARE 错误名称 CONDITION FOR 错误码(或错误条件)

2.5定义处理程序 

可以为 SQL 执行过程中发生的某种类型的错误定义特殊的处理程序。定义处理程序时,使用 DECLARE 语句的语法如下:
DECLARE 处理方式 HANDLER FOR 错误类型 处理语句

定义处理程序的几种方式 

#方法1:捕获sqlstate_value
DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SET @info = 'NO_SUCH_TABLE';
#方法2:捕获mysql_error_value
DECLARE CONTINUE HANDLER FOR 1146 SET @info = 'NO_SUCH_TABLE';
#方法3:先定义条件,再调用
DECLARE no_such_table CONDITION FOR 1146;
DECLARE CONTINUE HANDLER FOR NO_SUCH_TABLE SET @info = 'NO_SUCH_TABLE';
#方法4:使用SQLWARNING
DECLARE EXIT HANDLER FOR SQLWARNING SET @info = 'ERROR';
#方法5:使用NOT FOUND
DECLARE EXIT HANDLER FOR NOT FOUND SET @info = 'NO_SUCH_TABLE';
#方法6:使用SQLEXCEPTION
DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info = 'ERROR';

3. 流程控制

3.1 分支结构之 IF

3.11IF 语句的语法结构:

IF 表达式1 THEN 操作1
[ELSEIF 表达式2 THEN 操作2]……
[ELSE 操作N]
END IF
根据表达式的结果为 TRUE FALSE 执行相应的语句。这里 “[]” 中的内容是可选的。

3.12特点:

① 不同的表达式对应不同的操作
② 使用在 begin end

 举例:

声明存储过程 “update_salary_by_eid1” ,定义 IN 参数 emp_id ,输入员工编号。判断该员工
薪资如果低于 8000 元并且入职时间超过 5 年,就涨薪 500 元;否则就不变。
DELIMITER //
CREATE PROCEDURE update_salary_by_eid1(IN emp_id INT)
BEGIN

DECLARE emp_salary DOUBLE;
DECLARE hire_year DOUBLE;
SELECT salary INTO emp_salary FROM employees WHERE employee_id = emp_id;
SELECT DATEDIFF(CURDATE(),hire_date)/365 INTO hire_year
FROM employees WHERE employee_id = emp_id;
IF emp_salary < 8000 AND hire_year > 5
THEN UPDATE employees SET salary = salary + 500 WHERE employee_id = emp_id;
END IF;
END //
DELIMITER ;

3.2 分支结构之 CASE

3.21CASE 语句的语法结构1

#情况一:类似于switch
CASE 表达式
WHEN 值1 THEN 结果1或语句1(如果是语句,需要加分号)
WHEN 值2 THEN 结果2或语句2(如果是语句,需要加分号)
...
ELSE 结果n或语句n(如果是语句,需要加分号)
END [case](如果是放在begin end中需要加上case,如果放在select后面不需要)

CASE 语句的语法结构2

#情况二:类似于多重if
CASE
WHEN 条件1 THEN 结果1或语句1(如果是语句,需要加分号)
WHEN 条件2 THEN 结果2或语句2(如果是语句,需要加分号)
...
ELSE 结果n或语句n(如果是语句,需要加分号)
END [case](如果是放在begin end中需要加上case,如果放在select后面不需要)

举例

使用CASE流程控制语句的第2种格式,判断val是否为空、小于0、大于0或者等于0

CASE
WHEN val IS NULL THEN SELECT 'val is null';
WHEN val < 0 THEN SELECT 'val is less than 0';
WHEN val > 0 THEN SELECT 'val is greater than 0';
ELSE SELECT 'val is 0';
END CASE;

 3.3 循环结构之LOOP

LOOP 循环语句用来重复执行某些语句。 LOOP 内的语句一直重复执行直到循环被退出(使用 LEAVE 子句),跳出循环过程。

LOOP语句的基本格式

[loop_label:] LOOP
循环执行的语句
END LOOP [loop_label]
其中, loop_label 表示 LOOP 语句的标注名称,该参数可以省略。

举例

当市场环境变好时,公司为了奖励大家,决定给大家涨工资。声明存储过程
“update_salary_loop()” ,声明 OUT 参数 num ,输出循环次数。存储过程中实现循环给大家涨薪,薪资涨为原来的1.1 倍。直到全公司的平均薪资达到 12000 结束。并统计循环次数。

 

DELIMITER //
CREATE PROCEDURE update_salary_loop(OUT num INT)
BEGIN
DECLARE avg_salary DOUBLE;
DECLARE loop_count INT DEFAULT 0;
SELECT AVG(salary) INTO avg_salary FROM employees;
label_loop:LOOP
IF avg_salary >= 12000 THEN LEAVE label_loop;
END IF;
UPDATE employees SET salary = salary * 1.1;
SET loop_count = loop_count + 1;
SELECT AVG(salary) INTO avg_salary FROM employees;
END LOOP label_loop;
SET num = loop_count;
END //
DELIMITER ;

3.4 循环结构之WHILE

 WHILE语句创建一个带条件判断的循环过程。WHILE在执行语句执行时,先对指定的表达式进行判断,如果为真,就执行循环内的语句,否则退出循环。

语法:

[while_label:] WHILE 循环条件 DO
循环体
END WHILE [while_label];

 while_label为WHILE语句的标注名称;如果循环条件结果为真,WHILE语句内的语句或语句群被执行,直至循环条件为假,退出循环。

举例 

WHILE 语句示例, i 值小于 10 时,将重复执行循环过程
DELIMITER //
CREATE PROCEDURE test_while()
BEGIN
DECLARE i INT DEFAULT 0;
WHILE i < 10 DO
SET i = i + 1;
END WHILE;
SELECT i;
END //
DELIMITER ;
#调用
CALL test_while();

3.5 循环结构之REPEAT

REPEAT 语句创建一个带条件判断的循环过程。与 WHILE 循环不同的是, REPEAT 循环首先会执行一次循环,然后在 UNTIL 中进行表达式的判断,如果满足条件就退出,即 END REPEAT ;如果条件不满足,则会就继续执行循环,直到满足退出条件为止。

 REPEAT语句的基本格式

[repeat_label:] REPEAT
循环体的语句
UNTIL 结束循环的条件表达式
END REPEAT [repeat_label]
repeat_label REPEAT 语句的标注名称,该参数可以省略; REPEAT 语句内的语句或语句群被重复,直至expr_condition为真

 举例

DELIMITER //
CREATE PROCEDURE test_repeat()
BEGIN
DECLARE i INT DEFAULT 0;
REPEAT
SET i = i + 1;
UNTIL i >= 10
END REPEAT;
SELECT i;
END //
DELIMITER ;

对比三种循环结构:

1 、这三种循环都可以省略名称,但如果循环中添加了循环控制语句( LEAVE ITERATE )则必须添加名称。
2 LOOP :一般用于实现简单的 " " 循环 WHILE :先判断后执行 REPEAT :先执行后判断,无条件至少执行一次

 3.6 跳转语句之LEAVE语句

LEAVE 语句:可以用在循环语句内,或者以 BEGIN END 包裹起来的程序体内,表示跳出循环或者跳出程序体的操作。如果你有面向过程的编程语言的使用经验,你可以把 LEAVE 理解为 break

基本格式

LEAVE 标记名
其中, label 参数表示循环的标志。 LEAVE BEGIN ... END 或循环一起被使用。

举例

创建存储过程 “leave_begin()” ,声明 INT 类型的 IN 参数 num 。给 BEGIN...END 加标记名,并在
BEGIN...END 中使用 IF 语句判断 num 参数的值。
  •         如果num<=0,则使用LEAVE语句退出BEGIN...END
  •         如果num=1,则查询“employees”表的平均薪资;
  •         如果num=2,则查询“employees”表的最低薪资;
  •         如果num>2,则查询“employees”表的最高薪资。
IF 语句结束后查询 “employees” 表的总人数。

 

DELIMITER //
CREATE PROCEDURE leave_begin(IN num INT)
begin_label: BEGIN
IF num<=0
THEN LEAVE begin_label;
ELSEIF num=1
THEN SELECT AVG(salary) FROM employees;
ELSEIF num=2
THEN SELECT MIN(salary) FROM employees;
ELSE
SELECT MAX(salary) FROM employees;
END IF;
SELECT COUNT(*) FROM employees;
END //
DELIMITER ;

3.7 跳转语句之ITERATE语句

ITERATE 语句:只能用在循环语句( LOOP REPEAT WHILE 语句)内,表示重新开始循环,将执行顺序转到语句段开头处。如果你有面向过程的编程语言的使用经验,你可以把 ITERATE 理解为 continue ,意思为“ 再次循环

 语句基本格式

ITERATE label
label 参数表示循环的标志。 ITERATE 语句必须跟在循环标志前面。

举例

定义局部变量 num ,初始值为 0 。循环结构中执行 num + 1 操作。
        如果num < 10 ,则继续执行循环;
        如果num > 15 ,则退出循环结构;
DELIMITER //
CREATE PROCEDURE test_iterate()
BEGIN
DECLARE num INT DEFAULT 0;
my_loop:LOOP
SET num = num + 1;
IF num < 10
THEN ITERATE my_loop;
ELSEIF num > 15
END LOOP my_loop;
END //
DELIMITER ;

4. 游标

 4.1 什么是游标(或光标)

  •         游标,提供了一种灵活的操作方式,让我们能够对结果集中的每一条记录进行定位,并对指向的记录中的数据进行操作的数据结构。游标让 SQL 这种面向集合的语言有了面向过程开发的能力。
  •         在 SQL 中,游标是一种临时的数据库对象,可以指向存储在数据库表中的数据行指针。这里游标 充当了指针的作用 ,我们可以通过操作游标来对数据行进行操作。
  •         MySQL中游标可以在存储过程和函数中使用。

 4.2 使用游标步骤

第一步,声明游标

MySQL 中,使用 DECLARE 关键字来声明游标
语法的基本形式:
DECLARE cursor_name CURSOR FOR select_statement;

        这个语法适用于 MySQLSQL ServerDB2 MariaDB。如果是用 Oracle 或者 PostgreSQL,需要写成:

DECLARE cursor_name CURSOR IS select_statement;

要使用 SELECT 语句来获取数据结果集,而此时还没有开始遍历数据,这里 select_statement 代表的是SELECT 语句,返回一个用于创建游标的结果集。

比如:
DECLARE cur_emp CURSOR FOR
SELECT employee_id,salary FROM employees;


DECLARE cursor_fruit CURSOR FOR
SELECT f_name, f_price FROM fruits ;

第二步,打开游标

打开游标的语法:
OPEN cursor_name
当我们定义好游标之后,如果想要使用游标,必须先打开游标。打开游标的时候 SELECT 语句的查询结果集就会送到游标工作区,为后面游标的 逐条读取 结果集中的记录做准备。
OPEN cur_emp ;

第三步,使用游标(从游标中取得数据)

语法如下:
FETCH cursor_name INTO var_name [, var_name] ...
这句的作用是使用 cursor_name 这个游标来读取当前行,并且将数据保存到 var_name 这个变量中,游标指针指到下一行。如果游标读取的数据行有多个列名,则在 INTO 关键字后面赋值给多个变量名即可。
注意:var_name必须在声明游标之前就定义好。
FETCH cur_emp INTO emp_id, emp_sal ;
注意:游标的查询结果集中的字段数,必须跟 INTO 后面的变量数一致,否则,在存储过程执行的时候,MySQL 会提示错误。

第四步,关闭游标

CLOSE cursor_name
OPEN 就会有 CLOSE ,也就是打开和关闭游标。当我们使用完游标后需要关闭掉该游标。因为游标会 占用系统资源 ,如果不及时关闭, 游标会一直保持到存储过程结束 ,影响系统运行的效率。而关闭游标的操作,会释放游标占用的系统资源。
关闭游标之后,我们就不能再检索查询结果中的数据行,如果需要检索只能再次打开游标
CLOSE cur_emp;

4.3 举例

创建存储过程 “get_count_by_limit_total_salary()” ,声明 IN 参数 limit_total_salary DOUBLE 类型;声明OUT参数 total_count INT 类型。函数的功能可以实现累加薪资最高的几个员工的薪资值,直到薪资总和达到limit_total_salary 参数的值,返回累加的人数给 total_count
DELIMITER //
CREATE PROCEDURE get_count_by_limit_total_salary(IN limit_total_salary DOUBLE,OUT
total_count INT)
BEGIN
DECLARE sum_salary DOUBLE DEFAULT 0; #记录累加的总工资
DECLARE cursor_salary DOUBLE DEFAULT 0; #记录某一个工资值
DECLARE emp_count INT DEFAULT 0; #记录循环个数
#定义游标
DECLARE emp_cursor CURSOR FOR SELECT salary FROM employees ORDER BY salary DESC;
#打开游标
OPEN emp_cursor;
REPEAT
#使用游标(从游标中获取数据)
FETCH emp_cursor INTO cursor_salary;
SET sum_salary = sum_salary + cursor_salary;
SET emp_count = emp_count + 1;
UNTIL sum_salary >= limit_total_salary
END REPEAT;
SET total_count = emp_count;
#关闭游标
CLOSE emp_cursor;
END //
DELIMITER ;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值