MySQL数据库,变量、流程控制与游标

变量

系统变量

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

注:

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

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

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

 

查看系统变量

查看所有全局变量:

SHOW GLOBAL VARIABLES [LIKE '……'];

查看所有会话变量:

SHOW SESSION VARIABLES [LIKE '……'];

SHOW VARIABLES;-- 默认会话级别

 

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

 

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

SELECT @@global.变量名;

查看指定的会话变量的值

SELECT @@session.变量名;

或者

SELECT @@变量名;

 

修改系统变量的值

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

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

 

为某个系统变量赋值

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

SET GLOBAL 变量名 = 变量值;

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

 

为某个会话变量赋值

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

SET SESSION 变量名 = 变量值;

对当前会话有效

 

用户变量

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

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

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

 

会话用户变量

变量的定义:

方式一:使用SET的方式

SET @用户变量 = 值;

SET @用户变量 := 值;

 

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

SELECT 表达式 INTO @用户变量 [FROM等子句];

SELECT @用户变量 :=表达式 [FROM等子句];

 

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

SELECT @用户变量

SELECT @用户变量……

 

局部变量

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

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

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

BEGIN

声明局部变量

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

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

为局部变量赋值

SET 变量名 = 值;

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

查看局部变量的值

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

END

 

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

 

定义条件与处理程序

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

 

定义条件

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

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

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

关于错误码:

9de8de8ee2634a35a9f6703c1eb6359f.png

注:如果错误码是由数字组成的字符串,为了防止发生隐式转换,要在此错误码前加上SQLSTATE。

 

定义处理程序

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

DECLARE 处理方式 HANDLER FOR 错误类型 处理语句;

 

关于处理方式、错误类型、处理语句:(打字好累,截图偷懒)

c4211151d59b47e9b128ab0106594eab.png

 

例:使用CONTINUE的方式:(last_name字段有非空约束)

DELIMITER $

CREATE PROCEDURE test_exception()

BEGIN

DECLARE CONTINUE HANDLER FOR 1048 SET @prc_val = -1;

SET @ss = 1;

UPDATE test_1 SET last_name = NULL WHERE id = 1;

SET @ss = 9;

UPDATE test_1 SET last_name = 'Peter' WHERE id = 1;

END $

DELIMITER ;



CALL test_exception();

SELECT @ss,@prc_val;

结果为:

66ccd11d547743db96fb3171553b597a.png

 

使用EXIT的方式:(id字段有唯一性约束,表中已有id为2的记录)

DELIMITER $

CREATE PROCEDURE test_bb()

BEGIN

DECLARE EXIT HANDLER FOR 1062 SET @pro_val = 66;

SET @x = 1;

INSERT INTO test_1

VALUES(2,'Tony','@hyhi',5000);

SET @x = 9;

END $

DELIMITER ;



CALL test_bb();



SELECT @x,@pro_val;

结果为

43c72e291cdd41519d582dce682de992.png

 

流程控制

流程控制语句的作用是控制存储过程或存储函数中SQL语句的执行顺序。流程分为三类:

顺序结构:程序从上往下依次执行。

分支结构:程序按条件进行选择执行,从多条语句中选择其中一条执行。

循环结构:程序满足一定条件下,重复执行一组语句。

 流程控制语句主要有三类:

条件判断语句:IF语句和 CASE语句

循环语句:LOOP、WHILE和REPEAT语句

跳转语句:ITERATE、LEAVE语句

 

分支结构之IF

IF语句的语法结构是

IF search_condition THEN

    statement_list

ELSE IF search_condition THEN

    statement_list 

……

ELSE

    statement_list

END IF;

 

根据表达式的结果为TRUE或FALSE执行相应的语句。使用在BEGIN……END中。

 

 分支语句之CASE

CASE的语句格式有两种:

d36d181e67844d9786eb9de641f217ff.png

e52f4e8500cf45f383d1239c019e7c2d.png

用法与Java中和C语言的流程控制差不多,套模板就可以。

 

循环结构之LOOP

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

LOOP语句的格式:

18cca7af51fa4be19cf68907da1b9c00.png

其中,loop_label表示LOOP语句的标注名称,可以省略。

例:当id < 10时将重复执行循环过程。

DELIMITER  $

CREATE PROCEDURE test_loop()

BEGIN

DECLARE id INT DEFAULT 0;

aa:LOOP

    SET id = id + 1;

    IF id >= 10 THEN

        LEAVE aa;

    END IF;

END LOOP aa;

SELECT id;

END $

DELIMITER ;



CALL test_loop;

例:将所有的员工的工资提高1.1倍,如果没有达到公司平均工资3500以上,继续提高1.1倍,……直到公司平均工资达到3500以上。

DELIMITER  $

CREATE PROCEDURE test_loop_1(OUT num INT)

BEGIN

DECLARE avg_sal DECIMAL(7,2);

DECLARE loop_count INT DEFAULT 0;

SELECT AVG(sal) INTO avg_sal FROM emp_loop;

aaa: LOOP

    IF avg_sal >= 3500 THEN

        LEAVE aaa;

    END IF;-- 跳出循环的条件

    UPDATE emp_loop SET sal = sal * 1.1;-- 涨薪

    SELECT AVG(sal) INTO avg_sal FROM emp_loop;-- 更新员工平均工资

    SET loop_count = loop_count + 1;-- 更新循环次数

END LOOP aaa;

SELECT loop_count INTO num;

END $

DELIMITER ;



SET @x = 0;

CALL test_loop_1(@x);

SELECT @x;

 

循环结构之WHILE

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

81318577204441b4953776c88aab6db5.png

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

和C语言与Java中的while循环差不多。

 

例:(没有使用循环标签)

DELIMITER $

CREATE PROCEDURE test_while()

BEGIN

DECLARE num INT DEFAULT 0;

WHILE num <= 10 DO

    SET num = num + 1;

END WHILE;

SELECT num;

END $

DELIMITER ;



CALL test_while();

 

例:将所有的员工的工资降低到0.8倍,如果没有达到公司平均工资2500以下,继续提高降低到0.8倍,……直到公司平均工资达到2500以下。

DELIMITER  $

CREATE PROCEDURE test_while_1(OUT num INT)

BEGIN

DECLARE avg_sal DECIMAL(7,2);

DECLARE loop_count INT DEFAULT 0;

SELECT AVG(sal) INTO avg_sal FROM emp_loop;

WHILE avg_sal > 2500 DO

    UPDATE emp_loop SET sal = sal * 0.8;

    SELECT AVG(sal) INTO avg_sal FROM emp_loop;

    SET loop_count = loop_count + 1;

END WHILE;

SELECT loop_count INTO num;

END $

DELIMITER ;



SELECT AVG(sal) FROM emp_loop;



SET @s = 0;

CALL test_while_1(@s);

SELECT @s;

 

循环结构之REPEAT

REPEAT语句创建一个带条件判断的循环过程。与WHILE不同的是,REPEAT循环会首先执行一次循环,然后在UNTIL中进行表达式的判断,如果满足条件就退出。类似于C语言和Java中的do while循环。

8f3c52b5126b470fb3bbc05447e88d32.png

REPEAT就不写例子了,与前面的例子基本一样,只是格式不一样。

 

跳转结构之LEAVE语句

运行了LEAVE语句后,跳出整个循环。

格式:

LEAVE [label]

其中,label表示某个循环的标志。也可以给BEGIN …… END赋上标签,表示跳出此BEGIN …… END语句

相当于C语言和Java中的break语句。

 

跳转结构之ITERATE

ITERATE语句:只能用在循环语句中,表示跳过此次循环,进入到下一次循环。

格式:

ITERATE [label]

相当于C语言和Java中的continue语句。

 

游标

游标提供了一种灵活的操作方式,能够对结果集中的每一条记录进行定位,并对指向的记录中的数据进行操作的数据结构。

游标可以在存储过程存储函数中使用。

游标必须在声明处理程序之前被声明,并且变量和条件还必须在声明游标或处理程序之前被声明。

游标使用步骤:

①声明游标:

ae181ff34f9c46698637e38873204f26.png

②打开游标:

d5405aebb903449493fa1fe272c1dd5f.png

③使用游标:

b456a26f8569473cb9af09b15f2d19e5.png

④关闭游标:

bc18daa03b1345a68756e89e10881305.png

注:

游标的作用有点类似于Java的迭代器Iterator。每执行一次FETCH操作就类似于执行一次迭代器中的next方法的操作,返回当前指向的元素后,将指针指向下一个元素(即逐条读取,通常与循环一起使用)。

例:按员工从大到小开始计算,逐个累加员工工资直到总和达到20000.

DELIMITER $

CREATE PROCEDURE test_yb(IN total_sal DECIMAL(7,2),OUT total_count INT)

BEGIN

#声明局部变量

DECLARE sum_sal DECIMAL(7,2) DEFAULT 0.0;-- 记录累加的工资总和

DECLARE emp_sal DECIMAL(7.2) DEFAULT 0.0;-- 记录每一个员工的工资

DECLARE emp_count INT DEFAULT 0;-- 记录累加的人数

-- 声明游标

DECLARE emp_cursor CURSOR FOR SELECT sal FROM emp ORDER BY sal DESC;

-- 打开游标

OPEN emp_cursor;

-- 使用游标

REPEAT

    FETCH emp_cursor INTO emp_sal;

    SET sum_sal = sum_sal + emp_sal;

    SET emp_count = emp_count + 1;

UNTIL sum_sal >= total_sal END REPEAT;

SET total_count = emp_count;

-- 关闭游标

CLOSE emp_cursor;

END $

DELIMITER ;



SET @count_emp = 0;

CALL test_yb(20000,@count_emp);

SELECT @count_emp;

 

全局变量的持久化:

5c7246a1f0d84c6da101984018d7875d.png

 

 

  • 22
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二狗mao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值