MySQL的控制结构
在MySQL数据库中定义存储过程、触发器时,可能会用到条件判断、循环等控制结构,现总结如下:
一、数据准备
创建stu(学生)表,代码如下:
create table employee(
e_id int auto_increment,
e_name char(20),
sex char(2),
salary int,
phone char(20),
addr varchar(100),
constraint pk_employee_eid primary key(e_id)
);
为stu表输入数据,代码如下:
insert into employee(e_id,e_name,sex,salary,phone,addr)
values(1001,'张平','女',15000,'13703735566','河南省新乡市'),(1002,'王刚','男',8500,'13703714422','河南省郑州市'),
(1003,'张静静','女',5900,'13803716666','河南省郑州市'),(1004,'王涛','男',21000,'13703732211','河南省新乡市'),
(1005,'王鹏飞','男',15600,'13723750122','河南省安阳市'),(1006,'王强军','男',8900,'13736890126','河南省安阳市'),
(1007,'刘晶晶','女',5200,'13782576666','河南省安阳市'),(1008,'张梅梅','女',6500,'13688884412','河南省开封市');
二、条件判断
MySQL数据库中的判断结构有两种,IF结构和CASE结构。
1、IF判断结构
if 条件表达式1 then
命令序列1
[elseif 条件表达式2 then
命令序列2]
[elseif 条件表达式3 then
命令序列3]
...
[elseif 条件表达式n then
命令序列n]
[else
命令序列n+1]
end if;
例子:创建一个存储过程sp_emp_1,判断每一名员工的工资等级。代码如下:
delimiter //
create procedure sp_emp_1()
begin
declare emp_name char(20) default '';
declare emp_salary int default 0;
declare flag int default 1;
declare salary_grade char(20) default 0;
declare cur_emp cursor for select e_name,salary
from employee where addr='河南省安阳市';
declare continue handler for not found set flag:=0;
open cur_emp;
fetch cur_emp into emp_name,emp_salary;
while flag=1 do
if (emp_salary>=5000 and emp_salary<8000) then
set salary_grade:='一级工资';
elseif (emp_salary>=8000 and emp_salary<10000) then
set salary_grade:='二级工资';
elseif (emp_salary>=10000 and emp_salary<12000) then
set salary_grade:='三级工资';
elseif (emp_salary>=12000) then
set salary_grade:='四级工资';
else
set salary_grade:='试用期工资';
end if;
select emp_name,emp_salary,salary_grade;
fetch cur_emp into emp_name,emp_salary;
end while;
end //
delimiter ;
调用存储过程,运行结果如下:
mysql> call sp_emp_1();
+-----------+------------+--------------+
| emp_name | emp_salary | salary_grade |
+-----------+------------+--------------+
| 王鹏飞 | 15600 | 四级工资 |
+-----------+------------+--------------+
1 row in set (0.00 sec)
+-----------+------------+--------------+
| emp_name | emp_salary | salary_grade |
+-----------+------------+--------------+
| 王强军 | 8900 | 二级工资 |
+-----------+------------+--------------+
1 row in set (0.00 sec)
+-----------+------------+--------------+
| emp_name | emp_salary | salary_grade |
+-----------+------------+--------------+
| 刘晶晶 | 5200 | 一级工资 |
+-----------+------------+--------------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
2、CASE结构
CASE结构有两种用法:
(1)格式一
比较when后面的表达式和case后面的表达式,如果相等则执行该when后面的命令序列。
case 表达式
when 表达式1 then
命令序列1;
when 表达式2 then
命令序列2;
....
when 表达式n then
命令序列n;
else
命令序列n;
end CASE;
例子:
delimiter //
create procedure sp_emp_2()
begin
declare emp_addr varchar(100);
declare emp_cun_xinxiang int default 0;
declare emp_cun_anyang int default 0;
declare emp_cun_zhengzhou int default 0;
declare emp_cun_kaifeng int default 0;
declare flag int default 1;
declare cur_emp cursor for select addr from employee;
declare continue handler for not found set flag:=0;
open cur_emp;
fetch cur_emp into emp_addr;
while flag=1 do
case emp_addr
when '河南省新乡市' then
set emp_cun_xinxiang:=emp_cun_xinxiang+1;
when '河南省郑州市' then
set emp_cun_zhengzhou:=emp_cun_zhengzhou+1;
when '河南省安阳市' then
set emp_cun_anyang:=emp_cun_anyang+1;
when '河南省开封市' then
set emp_cun_kaifeng:=emp_cun_kaifeng+1;
end case;
fetch cur_emp into emp_addr;
end while;
select '各地市人数:',emp_cun_xinxiang,emp_cun_zhengzhou,emp_cun_anyang,emp_cun_kaifeng;
end //
delimiter ;
运行存储过程,查询结果如下:
mysql> call sp_emp_2();
+--------------------+------------------+-------------------+----------------+-----------------+
| 各地市人数: | emp_cun_xinxiang | emp_cun_zhengzhou | emp_cun_anyang | emp_cun_kaifeng |
+--------------------+------------------+-------------------+----------------+-----------------+
| 各地市人数: | 2 | 2 | 3 | 1 |
+--------------------+------------------+-------------------+----------------+-----------------+
1 row in set (0.01 sec)
(2)格式二
case后面空白,when后面直接加入判断条件,如果某个when后面的条件表达式成立,则执行其后面的命令序列。
case
when 条件表达式1 then
命令序列1;
when 条件表达式2 then
命令序列2;
....
when 条件表达式n then
命令序列n;
else
命令序列n+1;
end CASE;
例如:把存储过程sp_emp_1中的IF判断替换成CASE,代码如下:
delimiter //
create procedure sp_emp_3()
begin
declare emp_name char(20) default '';
declare emp_salary int default 0;
declare flag int default 1;
declare salary_grade char(20) default 0;
declare cur_emp cursor for select e_name,salary
from employee where sex='男';
declare continue handler for not found set flag:=0;
open cur_emp;
fetch cur_emp into emp_name,emp_salary;
while flag=1 do
case
when (emp_salary>=5000 and emp_salary<8000) then
set salary_grade:='一级工资';
when (emp_salary>=8000 and emp_salary<10000) then
set salary_grade:='二级工资';
when (emp_salary>=10000 and emp_salary<12000) then
set salary_grade:='三级工资';
when (emp_salary>=12000) then
set salary_grade:='四级工资';
else
set salary_grade:='试用期工资';
end case;
select emp_name,emp_salary,salary_grade;
fetch cur_emp into emp_name,emp_salary;
end while;
end //
delimiter ;
运行存储过程,查询结果如下:
mysql> call sp_emp_3();
+----------+------------+--------------+
| emp_name | emp_salary | salary_grade |
+----------+------------+--------------+
| 王刚 | 8500 | 二级工资 |
+----------+------------+--------------+
1 row in set (0.00 sec)
+----------+------------+--------------+
| emp_name | emp_salary | salary_grade |
+----------+------------+--------------+
| 王涛 | 21000 | 四级工资 |
+----------+------------+--------------+
1 row in set (0.00 sec)
+-----------+------------+--------------+
| emp_name | emp_salary | salary_grade |
+-----------+------------+--------------+
| 王鹏飞 | 15600 | 四级工资 |
+-----------+------------+--------------+
1 row in set (0.00 sec)
+-----------+------------+--------------+
| emp_name | emp_salary | salary_grade |
+-----------+------------+--------------+
| 王强军 | 8900 | 二级工资 |
+-----------+------------+--------------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
三、循环结构
1、while循环
while循环的语法如下:
while 循环条件 do
语句序列;
end while;
例子:定义一个函数func_sum,求1到n之间所有自然数的和。
delimiter //
create function func_sum(n int)
returns int no sql
begin
declare sumA int default 0;
declare i int default 1;
if n<=0 then
return 0;
else
while (i<=n) do
set sumA:=sumA+i;
set i:=i+1;
end while;
return sumA;
end if;
end //
delimiter ;
调用函数func_sum,结果如下:
mysql> select func_sum(100);
+---------------+
| func_sum(100) |
+---------------+
| 5050 |
+---------------+
1 row in set (0.00 sec)
mysql> select func_sum(-100);
+----------------+
| func_sum(-100) |
+----------------+
| 0 |
+----------------+
1 row in set (0.00 sec)
2、repeat循环
repeat循环的语法如下:
repeat
命令序列;
until 条件 end repeat;
例子:定义一个存储过程,显示100-999之间的水仙花数。水仙花数是指每一位数的三次方的和等于该数(例如:153=13+53+3^3)。
delimiter //
create procedure sp_sxh() no sql
begin
declare bai int;
declare shi int;
declare ge int;
declare n int default 100;
repeat
set bai:=floor(n/100);
set shi:=floor((n-bai*100)/10);
set ge:=n-bai*100-shi*10;
if power(bai,3)+power(shi,3)+power(ge,3)=n then
select n;
end if;
set n:=n+1;
until n>999 end repeat;
end //
delimiter ;
调用以上存储过程,查询结果如下:
mysql> call sp_sxh();
+------+
| n |
+------+
| 153 |
+------+
1 row in set (0.01 sec)
+------+
| n |
+------+
| 370 |
+------+
1 row in set (0.02 sec)
+------+
| n |
+------+
| 371 |
+------+
1 row in set (0.02 sec)
+------+
| n |
+------+
| 407 |
+------+
1 row in set (0.02 sec)
Query OK, 0 rows affected (0.05 sec)