背景

说到流程控制语句,我们在程序语法中用的比较多,比如C#的if..else...,while...,?: 等。同样的,在MySQL中,也有一些流程控制的语法,方便我们在写函数、存储过程的时候对逻辑进行控制和处理。

常见的过程式SQL语句可以用在存储过程或者函数体中。其中包括:IF函数、IF条件语句、CASE语句、LOOP语句、WHILE语句、REPEAT语句、LEAVE语句和ITERATE语句,它们极大的方便了我们进行流程控制。

下面我们一个一个来看。

流程语句分解

数据基础

  1. 1 mysql> select * from students;
  2. 2 +-----------+-------------+-------+---------+-----+
  3. 3 | studentid | studentname | score | classid | sex |
  4. 4 +-----------+-------------+-------+---------+-----+
  5. 5 | 1 | brand | 105.5 | 1 | 1 |
  6. 6 | 2 | helen | 98.5 | 1 | 0 |
  7. 7 | 3 | lyn | 97 | 1 | 0 |
  8. 8 | 4 | sol | 97 | 1 | 1 |
  9. 9 | 5 | b1 | 89 | 2 | 1 |
  10. 10 | 6 | b2 | 90 | 2 | 1 |
  11. 11 | 7 | c1 | 76 | 3 | 0 |
  12. 12 | 8 | c2 | 73.5 | 3 | 0 |
  13. 13 | 9 | lala | 73 | 0 | 0 |
  14. 14 | 10 | A | 100 | 3 | 1 |
  15. 15 | 16 | test1 | 100 | 0 | 1 |
  16. 16 | 17 | trigger2 | 107 | 0 | 1 |
  17. 17 | 22 | trigger1 | 100 | 0 | 0 |
  18. 18 +-----------+-------------+-------+---------+-----+
  19. 19 13 rows in set
  20. 20
  21. 21 mysql> select * from scores;
  22. 22 +-----------+---------+-------+
  23. 23 | scoregrad | downset | upset |
  24. 24 +-----------+---------+-------+
  25. 25 | A | 81 | 90 |
  26. 26 | B | 71 | 80 |
  27. 27 | C | 61 | 70 |
  28. 28 | D | 51 | 60 |
  29. 29 | S | 91 | 100 |
  30. 30 | S+ | 101 | 120 |
  31. 31 +-----------+---------+-------+
  32. 32 6 rows in set 

IF函数

有点类似C#语法中的三元表达式,有3个参数,第一个参数是表达式,后面两个是值,当表达式成立的时候取第一个值,表达式不成立的时候取第二个值。

  1. 1 if(expr,val1,val2); --语法 

输出学生信息中的名称和性别(1为男,0为女,这边用if函数进行转换)

  1. 1 mysql> select studentname,if(sex=0,'女','男') from students where classid<>0;
  2. 2 +-------------+---------------------+
  3. 3 | studentname | if(sex=0,'女','男') |
  4. 4 +-------------+---------------------+
  5. 5 | brand | |
  6. 6 | helen | |
  7. 7 | lyn | |
  8. 8 | sol | |
  9. 9 | b1 | |
  10. 10 | b2 | |
  11. 11 | c1 | |
  12. 12 | c2 | |
  13. 13 | A | |
  14. 14 +-------------+---------------------+
  15. 15 9 rows in set 

IF条件语句

IF语句用来进行条件判断,根据不同的条件执行不同的操作。该语句在执行时首先判断IF后的条件是否为真,则执行THEN后的语句,如果为假则继续判断IF语句直到为真为止,当以上都不满足时则执行ELSE语句后的内容。

  1. 1 IF condition THEN
  2. 2 ...
  3. 3 ELSEIF condition THEN
  4. 4 ...
  5. 5 ELSE
  6. 6 ...
  7. 7 END IF 

代码示例,根据考试成绩来分布不同的成绩等级

  1. 1 mysql>
  2. 2 /*如果存在函数func_test2,则删除*/
  3. 3 DROP FUNCTION IF EXISTS fun_if;
  4. 4 /*声明结束符为$*/
  5. 5 DELIMITER $
  6. 6 /*创建函数*/
  7. 7 CREATE FUNCTION fun_if(score DECIMAL(10,2))
  8. 8 RETURNS CHAR
  9. 9 BEGIN
  10. 10 DECLARE score_grad VARCHAR(5) DEFAULT '';
  11. 11 IF score>100 THEN SET score_grad='S';
  12. 12 ELSEIF (score BETWEEN 91 AND 100) THEN SET score_grad='A';
  13. 13 ELSEIF (score BETWEEN 81 AND 90) THEN SET score_grad='B';
  14. 14 ELSEIF (score BETWEEN 71 AND 80) THEN SET score_grad='C' ;
  15. 15 ELSE set score_grad='D';
  16. 16 END IF;
  17. 17 return score_grad;
  18. 18 END $
  19. 19 /*重置结束符为;*/
  20. 20 DELIMITER ;
  21. 21 Query OK, 0 rows affected 

执行结果

  1. 1 mysql> select fun_if(101),fun_if(100),fun_if(90),fun_if(80),fun_if(70);
  2. 2 +-------------+-------------+------------+------------+------------+
  3. 3 | fun_if(101) | fun_if(100) | fun_if(90) | fun_if(80) | fun_if(70) |
  4. 4 +-------------+-------------+------------+------------+------------+
  5. 5 | S | A | B | C | D |
  6. 6 +-------------+-------------+------------+------------+------------+
  7. 7 1 row in set 

CASE语句

CASE语句为多分支语句结构,该语句首先从WHEN后的VALUE中查找与CASE后的VALUE相等的值,如果查找到则执行该分支的内容,否则执行ELSE后的内容。CASE语句表示形式如下,类似C#中switch:

  1. 1 CASE expr
  2. 2 WHEN val1 THEN result1 or state1[;](可选项,如果是语句需要加分号,结果值可以加)
  3. 3 WHEN val2 THEN result2 or state2
  4. 4 ...
  5. 5 ELSE resultn or staten
  6. 6 END [CASE] (可选项,在begin end之间需加caseselect后就不需要) 

在select中使用示例

  1. 1 mysql> select studentname,case sex WHEN 0 THEN '女' WHEN 1 THEN '男' end as sex
  2. 2 from students where classid<>0;
  3. 3 +-------------+-----+
  4. 4 | studentname | sex |
  5. 5 +-------------+-----+
  6. 6 | brand | |
  7. 7 | helen | |
  8. 8 | lyn | |
  9. 9 | sol | |
  10. 10 | b1 | |
  11. 11 | b2 | |
  12. 12 | c1 | |
  13. 13 | c2 | |
  14. 14 | A | |
  15. 15 +-------------+-----+
  16. 16 9 rows in set 

在函数或存储过程中使用示例

  1. 1 mysql>
  2. 2 /*如果存在函数func_test2,则删除*/
  3. 3 DROP FUNCTION IF EXISTS fun_case;
  4. 4 /*声明结束符为$*/
  5. 5 DELIMITER $
  6. 6 /*创建函数*/
  7. 7 CREATE FUNCTION fun_case(sex INT)
  8. 8 RETURNS VARCHAR(20)
  9. 9 BEGIN
  10. 10 DECLARE sexStr VARCHAR(20) DEFAULT '';
  11. 11 CASE sex
  12. 12 WHEN 0 then set sexStr='女';
  13. 13 WHEN 1 then set sexStr='男';
  14. 14 ELSE set sexStr='不确定';
  15. 15 END CASE;
  16. 16 return sexStr;
  17. 17 END $
  18. 18 /*重置结束符为;*/
  19. 19 DELIMITER ;
  20. 20
  21. 21 Query OK, 0 rows affected 

函数执行结果

  1. 1 mysql> select studentname,fun_case(sex) from students where classid<>0;
  2. 2 +-------------+---------------+
  3. 3 | studentname | fun_case(sex) |
  4. 4 +-------------+---------------+
  5. 5 | brand | |
  6. 6 | helen | |
  7. 7 | lyn | |
  8. 8 | sol | |
  9. 9 | b1 | |
  10. 10 | b2 | |
  11. 11 | c1 | |
  12. 12 | c2 | |
  13. 13 | A | |
  14. 14 +-------------+---------------+
  15. 15 9 rows in set 

循环语句while

循环语句while 类似于C#中的while循环,我们知道在C#的while 或者 for 语句中,经常有用到两个关键语法:跳过当前循环(continue) 和 结束循环(break)。

同样的,在MySQL中也有两个语法对应跳过和结束循环。

  1. 1 ITERATE loop_label; --跳过当前循环
  1. 1 LEAVE loop_label; --结束循环
while 语法
  1. 1 [loop_label:]while condition do
  2. 2 --Todo:loop body
  3. 3 end while [loop_label]; 

loop_label:循环标签,和iterateleave结合用于在循环内部对循环进行控制:如:跳过本次循环、结束循环。

condition:循环条件,当满足条件的时候,就会执行循环体,条件不成立的时候结束循环。

while示例

下面脚本代码演示了将students表中studentid在给定数值范围内的数据存储到另外一张表中。

  1. 1 /*先清除studentCount表记录*/
  2. 2 truncate table studentcount;
  3. 3 /*存储过程如果存在则删除*/
  4. 4 DROP PROCEDURE IF EXISTS sp_while1;
  5. 5 /*声明结束符为$*/
  6. 6 DELIMITER $
  7. 7 /*创建存储过程*/
  8. 8 CREATE PROCEDURE sp_while1(varial_count int)
  9. 9 BEGIN
  10. 10 DECLARE idx int DEFAULT 1;
  11. 11 DECLARE uname VARCHAR(30) DEFAULT '';
  12. 12 loop_label:WHILE idx<=varial_count DO
  13. 13 select studentname into uname from students where studentid = idx;
  14. 14 INSERT into studentCount values (idx,uname);
  15. 15 SET idx=idx+1;
  16. 16 END WHILE;
  17. 17 END $
  18. 18 /*结束符置为;*/
  19. 19 DELIMITER ; 

调用存储过程,给定数值范围是10,所以这边取出1~10的数据存储到studentCount表中

  1. 1 mysql> CALL sp_while1(10);
  2. 2 Query OK, 1 row affected
  3. 3
  4. 4 mysql> select * from studentCount;
  5. 5 +-----------+-------------+
  6. 6 | studentid | studentname |
  7. 7 +-----------+-------------+
  8. 8 | 1 | brand |
  9. 9 | 2 | helen |
  10. 10 | 3 | lyn |
  11. 11 | 4 | sol |
  12. 12 | 5 | b1 |
  13. 13 | 6 | b2 |
  14. 14 | 7 | c1 |
  15. 15 | 8 | c2 |
  16. 16 | 9 | lala |
  17. 17 | 10 | A |
  18. 18 +-----------+-------------+
  19. 19 10 rows in set 
while示例:包含iterate/leave

前面我们说明过了,iterate 和 leave 分别代表跳过本次循环,类似于C#中的continue和break。我们在例子中测试下吧:

遇到studentname=lala时,结束循环,遇到偶数时候跳过单次循环。

  1. 1 /*先清除studentCount表记录*/
  2. 2 truncate table studentcount;
  3. 3 /*存储过程如果存在则删除*/
  4. 4 DROP PROCEDURE IF EXISTS sp_while2;
  5. 5 /*声明结束符为$*/
  6. 6 DELIMITER $
  7. 7 /*创建存储过程*/
  8. 8 CREATE PROCEDURE sp_while2(varial_count int)
  9. 9 BEGIN
  10. 10 DECLARE idx int DEFAULT 0;
  11. 11 DECLARE uname VARCHAR(30) DEFAULT '';
  12. 12 loop_label:WHILE idx<=varial_count DO
  13. 13 SET idx=idx+1;
  14. 14 select studentname into uname from students where studentid = idx;
  15. 15 /*如果遇到studentname为lala的同学,结束循环*/
  16. 16 IF uname='lala' THEN
  17. 17 LEAVE loop_label;
  18. 18 /*如果idx为偶数,则跳过本次循环*/
  19. 19 ELSEIF idx%2=0 THEN
  20. 20 ITERATE loop_label;
  21. 21 END IF;
  22. 22 INSERT into studentCount values (idx,uname);
  23. 23 END WHILE;
  24. 24 END $
  25. 25 /*结束符置为;*/
  26. 26 DELIMITER ; 

调用存储过程,输出符合要求的数据:

  1. 1 mysql> CALL sp_while2(10);
  2. 2 Query OK, 1 row affected
  3. 3
  4. 4 mysql> select * from studentCount;
  5. 5 +-----------+-------------+
  6. 6 | studentid | studentname |
  7. 7 +-----------+-------------+
  8. 8 | 1 | brand |
  9. 9 | 3 | lyn |
  10. 10 | 5 | b1 |
  11. 11 | 7 | c1 |
  12. 12 +-----------+-------------+
  13. 13 4 rows in set

循环语句repeat

repeat语法
  1. 1 [loop_label:]repeat
  2. 2 -- Todo loop body
  3. 3 until condition
  4. 4 end repeat [loop_label]; 

可以对比下上面while的语法,while是先判断条件是否成立再执行循环体,repeat循环更像是的do...while循环,就是循环始终都会先执行一次,然后再判断结束循环的条件,不满足结束条件,循环体继续执行。

  1. 1 /*先清除studentCount表记录*/
  2. 2 truncate table studentcount;
  3. 3 /*存储过程如果存在则删除*/
  4. 4 DROP PROCEDURE IF EXISTS sp_repeat;
  5. 5 /*声明结束符为$*/
  6. 6 DELIMITER $
  7. 7 /*创建存储过程*/
  8. 8 CREATE PROCEDURE sp_repeat(varial_count int)
  9. 9 BEGIN
  10. 10 DECLARE idx int DEFAULT 0;
  11. 11 DECLARE uname VARCHAR(30) DEFAULT '';
  12. 12 loop_label:REPEAT
  13. 13 SET idx=idx+1;
  14. 14 select studentname into uname from students where studentid = idx;
  15. 15 /*如果遇到studentname为lala的同学,结束循环*/
  16. 16 IF uname='lala' THEN
  17. 17 LEAVE loop_label;
  18. 18 /*如果idx为偶数,则跳过本次循环*/
  19. 19 ELSEIF idx%2=0 THEN
  20. 20 ITERATE loop_label;
  21. 21 END IF;
  22. 22 INSERT into studentCount values (idx,uname);
  23. 23 UNTIL idx>varial_count
  24. 24 END REPEAT;
  25. 25 END $
  26. 26 /*结束符置为;*/
  27. 27 DELIMITER ; 

注意条件的变化,下面是调用存储过程,输出需要的数据:

  1. 1 mysql> CALL sp_repeat(10);
  2. 2 Query OK, 1 row affected
  3. 3
  4. 4 mysql> select * from studentCount;
  5. 5 +-----------+-------------+
  6. 6 | studentid | studentname |
  7. 7 +-----------+-------------+
  8. 8 | 1 | brand |
  9. 9 | 3 | lyn |
  10. 10 | 5 | b1 |
  11. 11 | 7 | c1 |
  12. 12 +-----------+-------------+
  13. 13 4 rows in set 

循环语句loop

loop语法
  1. 1 [loop_label:]loop
  2. 2 --Todo loop body
  3. 3 end loop [loop label]; 

loop不像while和repeat那样有控制条件,条件不符合的时候会跳出。所以它实际上是会一直执行的,如果不主动中断或者跳出的话,类似于一个死循环,需要在循环体中使用iterate或者leave来控制循环的执行。

  1. 1 /*先清除studentCount表记录*/
  2. 2 truncate table studentcount;
  3. 3 /*存储过程如果存在则删除*/
  4. 4 DROP PROCEDURE IF EXISTS sp_loop;
  5. 5 /*声明结束符为$*/
  6. 6 DELIMITER $
  7. 7 /*创建存储过程*/
  8. 8 CREATE PROCEDURE sp_loop(varial_count int)
  9. 9 BEGIN
  10. 10 DECLARE idx int DEFAULT 0;
  11. 11 DECLARE uname VARCHAR(30) DEFAULT '';
  12. 12 loop_label:LOOP
  13. 13 SET idx=idx+1;
  14. 14 select studentname into uname from students where studentid = idx;
  15. 15 /*如果遇到studentname为lala的同学,结束循环*/
  16. 16 IF uname='lala' THEN
  17. 17 LEAVE loop_label;
  18. 18 /*如果idx为偶数,则跳过本次循环*/
  19. 19 ELSEIF idx%2<>0 THEN
  20. 20 ITERATE loop_label;
  21. 21 /*这边加一个终结计数跳出的条件*/
  22. 22 ELSEIF idx>varial_count THEN
  23. 23 LEAVE loop_label;
  24. 24 END IF;
  25. 25 INSERT into studentCount values (idx,uname);
  26. 26
  27. 27 END LOOP;
  28. 28 END $
  29. 29 /*结束符置为;*/
  30. 30 DELIMITER ; 

调用存储过程,并输出你需要的数据:

  1. 1 mysql> CALL sp_loop(6);
  2. 2 Query OK, 1 row affected
  3. 3
  4. 4 mysql> select * from studentCount;
  5. 5 +-----------+-------------+
  6. 6 | studentid | studentname |
  7. 7 +-----------+-------------+
  8. 8 | 2 | helen |
  9. 9 | 4 | sol |
  10. 10 | 6 | b2 |
  11. 11 +-----------+-------------+
  12. 12 3 rows in set

总结

1、了解了IF函数,它常用在SELECT语句中,类似于C#中的三元表达式。
2、IF条件表达式,类似于C#中的IF... ELSE...,多用于函数或存储过程中的判断选择逻辑。
3、了解CASE语句的两种用法,一种用在SELECT中使用,一种用在函数和存储过程中。
4、了解了三种循环体的使用,while、repeat分别对应C#中的while 和 do while循环,loop类似于一个while(true)的死循环。
5、循环体都包含在begin end中,循环体的控制依靠leave和iterate,leave相当于break,即退出整个循环体,iterate类似于continue,即跳过本次循环。

MySQL全面瓦解20:可编程性之流程控制语句的更多相关文章

  1. 关系数据库SQL之可编程性事务

    前言 前面关系数据库SQL之可编程性函数(用户自定义函数)一文提到关系型数据库提供了可编程性的函数.存储过程.事务.触发器及游标,前文已介绍了函数.存储过程,本文来介绍一下事务的使用.(还是以前面的银 ...

  2. 关系数据库SQL之可编程性存储过程

    前言 前面关系数据库SQL之可编程性函数(用户自定义函数)一文提到关系型数据库提供了可编程性的函数.存储过程.事务.触发器及游标,前文已介绍了函数,本文来介绍一下存储过程的创建.执行.删除.(还是以前 ...

  3. 关系数据库SQL之可编程性函数(用户自定义函数)

    前言 在关系型数据库中除了前面几篇基本的数据库和数据表操作之外,还提供了可编程性的函数.存储过程.事务.触发器及游标. 本文介绍的是函数. 函数分为两种: 系统函数 用户自定义函数 准备工作 这里以银 ...

  4. 《[MySQL技术内幕:SQL编程》读书笔记

    <[MySQL技术内幕:SQL编程>读书笔记 2019年3月31日23:12:11 严禁转载!!! <MySQL技术内幕:SQL编程>这本书是我比较喜欢的一位国内作者姜承尧, ...

  5. MySQL全面瓦解13:系统函数相关

    概述 提到MySQL的系统函数,我们前面有使用过聚合函数,其实只是其中一小部分.MySQL提供很多功能强大.方便易用的函数,使用这些函数,可以极大地提高用户对于数据库的管理效率,并更加灵活地满足不同用 ...

  6. MySQL全面瓦解23:MySQL索引实现和使用

    MySQL索引实现 上一篇我们详细了解了B+树的实现原理(传送门).我们知道,MySQL内部索引是由不同的引擎实现的,主要包含InnoDB和MyISAM这两种,并且这两种引擎中的索引都是使用b+树的结 ...

  7. MySQL全面瓦解24:构建高性能索引(策略篇)

    学习如果构建高性能的索引之前,我们先来了解下之前的知识,以下两篇是基础原理,了解之后,对面后续索引构建的原则和优化方法会有更清晰的理解: MySQL全面瓦解22:索引的介绍和原理分析 MySQL全面瓦 ...

  8. MySQL全面瓦解25:构建高性能索引(案例分析篇)

    回顾一下上面几篇索引相关的文章: MySQL全面瓦解22:索引的介绍和原理分析 MySQL全面瓦解23:MySQL索引实现和使用 MySQL全面瓦解24:构建高性能索引(策略篇) 索引的十大原则 1. ...

  9. 关系数据库SQL之可编程性触发器

    前言 前面关系数据库SQL之可编程性函数(用户自定义函数)一文提到关系型数据库提供了可编程性的函数.存储过程.事务.触发器及游标,前文已介绍了函数.存储过程.事务,本文来介绍一下触发器的使用.(还是以 ...

随机推荐

  1. flink1.11报错No ExecutorFactory found to execute the application

    使用flink1.11版本时,报错:No ExecutorFactory found to execute the application 查找maven下载的依赖,发现没有下载flink-clien ...

  2. Fabric 配置 order节点问题

    问题描述: Error: failed to create deliver client: orderer client failed to connect to orderer.example.co ...

  3. react第十三单元(react路由-react路由的跳转以及路由信息) #课程目标

    第十三单元(react路由-react路由的跳转以及路由信息) #课程目标 熟悉掌握路由的配置 熟悉掌握跳转路由的方式 熟悉掌握路由跳转传参的方式 可以根据对其的理解封装一个类似Vue的router- ...

  4. 闭关修炼180天--手写IOC和AOP(xml篇)

    闭关修炼180天--手写IOC和AOP(xml篇) 帝莘 首先先分享一波思维导图,涵盖了一些Spring的知识点,当然这里并不全面,后期我会持续更新知识点. 在手写实现IOC和AOP之前(也就是打造一 ...

  5. 流程控制之☞ while 和 for 的故事

    学习三连鞭... 什么是循环? 为什么要有循环? 如何用循环? 循环的基本语法:while   和     for 先来看while循环: while条件:首先得是个循环体. 1.如果条件为真,那么循 ...

  6. win10新版wsl2使用指南

    本篇文章会介绍win10中wsl2的安装和使用以及遇到的常见问题比如如何固定wsl2地址等问题的总结. 一.wsl2简介 wsl是适用于 Linux 的 Windows 子系统,安装指南:适用于 Li ...

  7. 3.mysql小表驱动大表的4种表连接算法

    小表驱动大表 1.概念 驱动表的概念是指多表关联查询时,第一个被处理的表,使用此表的记录去关联其他表.驱动表的确定很关键,会直接影响多表连接的关联顺序,也决定了后续关联时的查询性能. 2.原则 驱动表 ...

  8. 实验3 C语言分支语句和循环语句编程应用(友好猜日期^_^)

    实验任务一 #include <stdio.h> #include <math.h> int main(){ float a, b, c, x1, x2; float delt ...

  9. H5-地理定位/本地存储/拖放

    一.地理定位 Geolocation 兼容性:Internet Explorer 9+, Firefox, Chrome, Safari 和 Opera 支持Geolocation(地理定位). 一次 ...

  10. linux零基础之--常用命令

    linux: 用户命令 linux 目录切换命令 linux文件命令 linux : vi编辑器 linux:打包压缩