概述
本章,您将学习 MySQL 当中的流程控制。流程控制用来实现条件判断和循环逻辑,主要用在 MySQL 的存储过程、存储函数、触发器中。
流程控制主要包括三类:
- 分支结构
- 循环结构
- 跳转控制
分支结构
if 函数
基本语法为:
if(表达式, 值1, 值2)
当表达式为真,则输出 值1,当表达式为假,则输出 值2
一个简单的例子:
select if(50>100,'真','假') as `test`;
+------+
| test |
+------+
| 假 |
+------+
1 row in set (0.00 sec)
在存储函数中的简单使用:
use home;
delimiter //
create function get_salary_grade( salary decimal(10,2) ) returns char(1)
begin
declare grade char(1) default 'd';
# if 函数的多层嵌套
set grade:=if( salary <= 5000, 'd',
if( salary <= 8000, 'c',
if( salary <= 10000 , 'b', 'a'))
);
return grade;
end //
delimiter ;
select get_salary_grade(6000);
+------------------------+
| get_salary_grade(6000) |
+------------------------+
| c |
+------------------------+
1 row in set (0.00 sec)
drop function if exists home.get_salary_grade;
if 结构
该结构只能存在于存储过程或存储函数或触发器的 begin...end
代码块中,不能单独存在,基本语法为:
...
begin
if 条件1 then 语句1;
elseif 条件2 then 语句2;
...
[else 语句n];
end if;
end
...
上面的 if 函数改造为 if 分支结构:
use home;
delimiter //
create function get_salary_grade_if( salary decimal(10,2) ) returns char(1)
begin
declare grade char(1) default 'd';
if salary <= 5000 then set grade:='d';
elseif salary <= 8000 then set grade:='c';
elseif salary <= 10000 then set grade:='b';
else set grade:='a';
end if;
return grade;
end //
delimier ;
select get_salary_grade_if(15000);
+----------------------------+
| get_salary_grade_if(15000) |
+----------------------------+
| a |
+----------------------------+
1 row in set (0.00 sec)
drop function if exists home.get_salary_grade_if;
case 结构
在前面的 《MySQL基础08 --- DQL2》 文章中介绍过 case 的单独用法,当作为 select
的查询列表时,case 有两种语法:
# 第一种
## 当你不键入 else 后面的语法时,没有匹配到的则会以 null 进行显示。
case 表达式或字段或变量
when 常量1 then 要显示的值1或者语句1
when 常量2 then 要显示的值2或者语句2
...
else 要显示的值n或者语句n或者字段
end
## 示例如下:
select
name,
case Continent
when 'Asia' then '亚洲'
when 'north america' then '北美'
else Continent
end as `temp`
from
country;
# 第二种
## 当你不键入 else 后面的语法时,没有匹配到的则会以 null 进行显示。
case
when 条件1 then 要显示的值1或者语句1
when 条件2 then 要显示的值2或者语句2
...
else 要显示的值n或者语句n
end
## 示例如下:
select
name,
case
when Continent = 'Asia' then '亚洲'
when Continent in ('north america', 'Africa') then 'A_N'
else Continent
end as `temp`
from
country;
小提示
上面的两种语法中,
then
关键字后面的 **语句** 必须是 **标量子查询**(结果集只有一行一列的查询)。case when then
语法也可以用在 begin...end
代码块中,其语法如下:
# 第一种
## 当你不键入 else 后面的语法时,没有匹配到的则会以 null 进行显示。
...
begin
case 表达式或字段或变量
when 要判断的值 then 语句1;
when 要判断的值 then 语句2;
when 要判断的值 then 语句3;
when 要判断的值 then 语句4;
...
else 语句n;
end case;
end
...
# 第二种
## 当你不键入 else 后面的语法时,没有匹配到的则会以 null 进行显示。
...
begin
case
when 判断条件1 then 语句1;
when 判断条件2 then 语句2;
when 判断条件3 then 语句3;
...
else 语句n;
end case;
end
...
同样的要求 —— then
关键字后面的 语句 必须是 标量子查询(结果集只有一行一列的查询)。
如下面的例子:
use world;
delimiter //
create procedure demo1( in cname char(52) )
begin
set @n:=1;
select gnp into @n from country where name=cname;
case
# concat 函数用来拼接字符串
when @n>=10000 then select concat(name, '+', gnp, '+', code) from country where name=cname;
else select @n;
end case;
end //
delimiter ;
call demo1('china');
+-----------------------------------+
| concat(name, '+', gnp, '+', code) |
+-----------------------------------+
| China+982268.00+CHN |
+-----------------------------------+
1 row in set (0.04 sec)
drop procedure if exists world.demo1;
循环结构
有三个循环结构:
- WHILE 循环
- LOOP 循环
- REPEAT 循环
WHILE 循环
基本语法为:
[标签名:]while 循环条件 do
循环体;
end while [标签名];
写一个无参存储过程,求等差数列的前 100 项的和,公差为 1,第一项的值为 1,第 100 项的值为 100。
use world;
delimiter //
create procedure count_sum()
begin
declare x int default 0;
declare y int default 1;
while y<= 100 do
set x:=x+y;
set y:=y+1;
end while;
select x;
end //
delimiter ;
call count_sum();
+------+
| x |
+------+
| 5050 |
+------+
1 row in set (0.00 sec)
drop procedure if exists world.count_sum;
LOOP 循环
基本语法为:
[标签名:]loop
循环体;
end loop [标签名];
写一个无参存储过程,求等比数列前 20 项的和,公比为 2,第一项的值为 1(2的0次方),第 20 项的值为 1048576(2的19次方)
use world;
delimiter //
create procedure geometric_progression()
begin
declare x int default 0;
declare y int default 0;
n:loop
set x:=x+power(2,y);
set y:=y+1;
if y> 20 then leave n;
end if;
end loop n;
select x;
end //
delimiter ;
call geometric_progression();
+---------+
| x |
+---------+
| 2097151 |
+---------+
1 row in set (0.00 sec)
drop procedure world.geometric_progression;
power(x,y) 函数表示以 x 为底数且以 y 为指数的幂运算,例如 power(2,3) 的输出为 8:
select power(2,3);
+------------+
| power(2,3) |
+------------+
| 8 |
+------------+
需要注意的是,LOOP 循环默认是一个是死循环,因此你需要使用相关的关键字进行跳出,在上面的例子中,使用的是 leave
关键字。
REPEAT 循环
基本语法为:
[标签名称:]repeat
循环体
until 结束循环的条件
end repeat [标签名称];
写一个有参存储过程,求等差数列的前 n 项的和,公差为 1,第一项的值为 1:
use world;
delimiter //
create procedure sum_repeat(in n int)
begin
declare x int default 1;
repeat
set x:=x+n;
set n:=n-1;
until n=1
end repeat;
select x;
end //
delimiter ;
call sum_repeat(50);
+------+
| x |
+------+
| 1275 |
+------+
1 row in set (0.00 sec)
drop procedure world.sum_repeat;
跳转控制
主要有两个:
leave
- 用于退出循环或begin...end
代码块iterate
- 跳过当次的循环并进入到下一次循环
leave
退出循环的例子在上面的 LOOP 循环中已经演示
再来看一个 iterate
的例子:
use home;
create table p1(
name varchar(10) not null
);
delimiter //
create procedure insert_odd_num(in y int)
begin
declare x int default 0;
a:while x<y do
set x:=x+1;
if mod(x,2)=0 then iterate a;
end if;
insert into p1 values(concat('jack',x));
end while a;
end //
delimiter ;
call insert_odd_num(19);
select * from p1;
+--------+
| name |
+--------+
| jack1 |
| jack3 |
| jack5 |
| jack7 |
| jack9 |
| jack11 |
| jack13 |
| jack15 |
| jack17 |
| jack19 |
+--------+
版权声明:「自由转载-保持署名-非商业性使用-禁止演绎 3.0 国际」(CC BY-NC-ND 3.0)

用一杯咖啡支持我们,我们的每一篇[文档]都经过实际操作和精心打磨,而不是简单地从网上复制粘贴。期间投入了大量心血,只为能够真正帮助到您。
暂无评论