4.存储过程(二)

2021-02-05  本文已影响0人  21号新秀_邓肯

6.语法

存储过程是可以编程的,意味着可以使用变量,表达式,控制结构 , 来完成比较复杂的功能。

6.1 变量

(1) DECLARE

通过 DECLARE 可以定义一个局部变量,该变量的作用范围只能在 BEGIN…END 块中。

DECLARE var_name[,...] type [DEFAULT value] 1

示例:

delimiter $
create procedure pro_test2()
begin

    declare num int default 5;
    select num + 10;

end$
delimiter ; 

(2) SET

直接赋值使用 SET,可以赋常量或者赋表达式,具体语法如下:

SET var_name = expr [, var_name = expr] ... 1

示例 :

DELIMITER $

CREATE PROCEDURE pro_test3()
BEGIN

    DECLARE NAME VARCHAR(20);
    SET NAME = 'MYSQL';
    SELECT NAME;

END$

DELIMITER ;

也可以通过select ... into 方式进行赋值操作 :

DELIMITER $
CREATE PROCEDURE pro_test5()
BEGIN

    declare countnum int;
    select count(*) into countnum from city;

    select countnum;
END$
DELIMITER ; 

6.2 if条件判断

1.语法:

if search_condition then statement_list 

[elseif search_condition then statement_list] ... 

[else statement_list] 

end if;

2.需求:

根据定义的身高变量,判定当前身高的所属的身材类型

180 及以上 ----------> 身材高挑

170 - 180 ---------> 标准身材

170 以下 ----------> 一般身材

3.示例:

delimiter $

create procedure pro_test6()
begin

    declare height int default 175;
    declare description varchar(50);

    if height >= 180 then
        set description = '身材高挑';
    elseif height >= 170 and height < 180 then
        set description = '标准身材';
    else
        set description = '一般身材';
    end if;

    select description;

end$
delimiter ; 

调用结果为 :

image.png

6.3 传递参数

语法格式 :

create procedure procedure_name([in/out/inout] 参数名 参数类型) 

... 

IN : 该参数可以作为输入,也就是需要调用方传入值 , 默认 

OUT: 该参数作为输出,也就是该参数可以作为返回值 

INOUT: 既可以作为输入参数,也可以作为输出参数

1. IN - 输入

需求 :

根据定义的身高变量,判定当前身高的所属的身材类型

delimiter $

create procedure pro_test5(in height int)
begin

    declare description varchar(50) default '';
    if height >= 180 then
        set description = '身材高挑';
    elseif height >= 170 and height < 180 then
        set description = '标准身材';
    else
        set description = '一般身材';
    end if;

    select concat('身高 ', height, '对应的身材类型为:', description);

end$
delimiter ; 

2. OUT 输出

需求 :

根据传入的身高变量,获取当前身高的所属的身材类型

示例:

delimiter $
create PROCEDURE pro_test5(in height int, out description varchar(100))
begin
    if height >= 180 then
        set description = '身材高挑';
    elseif height >= 170 and height < 180 then
        set description = '标准身材';
    else
        set description = '一般身材';
    end if;
end $
#调用
#set @bName
$ #其实这个定义用户变量过程是不用写的,直接按照下面调用的写法就行
call pro_test5(180, @bName)$
select @bName$

小知识

@description : 这种变量要在变量名称前面加上“@”符号,叫做用户会话变量,代表整个会话过程他都是有作用的,这个类似于全局变量一样。

@@global.sort_buffffer_size : 这种在变量前加上 "@@" 符号, 叫做 系统变量

6.4 case结构

1.语法:

方式一 : 

CASE case_value 

    WHEN when_value THEN statement_list 

    [WHEN when_value THEN statement_list] ... 

    [ELSE statement_list] 

END CASE; 

方式二 : 
CASE

    WHEN search_condition THEN statement_list 

    [WHEN search_condition THEN statement_list] ... 

    [ELSE statement_list] 

END CASE; 

需求:

给定一个月份, 然后计算出所在的季度

示例:

delimiter $
create procedure pro_test9(monthParam int)
begin
    declare result varchar(20);
    case
        when monthParam >= 1 and monthParam <= 3 then
            set result = '第一季度';
        when monthParam >= 4 and monthParam <= 6 then
            set result = '第二季度';
        when monthParam >= 7 and monthParam <= 9 then
            set result = '第三季度';
        when monthParam >= 10 and monthParam <= 12 then
            set result = '第四季度';
        end case;
    select concat('您输入的月份为 :', monthParam, ' , 该月份为 : ', result) as content;
end$ delimiter ;

6.5 while 循环

1.语法结构:

while search_condition do 
    statement_list 
end while;

2.需求

计算从1加到n的值

3. 示例

delimiter $

create procedure pro_test8(n int)
begin

    declare total int default 0;
    declare num int default 1;
    
    while num <= n
        do
            set total = total + num;
            set num = num + 1;
        end while;
    select total;

end$
delimiter ;

6.6 repeat 结构

有条件的循环控制语句, 当满足条件的时候退出循环 。while 是满足条件才执行,repeat 是满足条件就退出循环。

1.语法结构:

REPEAT 

    statement_list 

    UNTIL search_condition 

END REPEAT; 

2.需求

计算从1加到n的值

3. 示例

delimiter $
create procedure pro_test10(n int)
begin

    declare total int default 0;
    repeat
        set total = total + n;
        set n = n - 1;
    until n = 0
        end repeat;
    select total;

end$
delimiter ;

6.7 loop语句

LOOP 实现简单的循环,退出循环的条件需要使用其他的语句定义,通常可以使用 LEAVE 语句实现,具体语法如下:

[begin_label:] LOOP 
    statement_list 
END LOOP [end_label]

如果不在 statement_list 中增加退出循环的语句,那么 LOOP 语句可以用来实现简单的死循环。

6.8 leave 语句

用来从标注的流程构造中退出,通常和 BEGIN ... END 或者循环一起使用。下面是一个使用 LOOP 和 LEAVE 的简单例子 , 退出循环:

delimiter $
CREATE PROCEDURE pro_test11(n int)
BEGIN

    declare total int default 0;
    ins:
    LOOP
        IF n <= 0 then
            leave ins;
        END IF;
        set total = total + n;
        set n = n - 1;
    END LOOP ins;
    select total;

END$
delimiter ;

6.9 游标/光标

游标是用来存储查询结果集的数据类型 , 在存储过程和函数中可以使用光标对结果集进行循环的处理。

光标的使用包括光标的声明、OPEN、FETCH 和 CLOSE,其语法分别如下。

1.声明光标:

DECLARE cursor_name CURSOR FOR select_statement ; 

2.OPEN 光标:

OPEN cursor_name ;

3. FETCH 光标:

FETCH cursor_name INTO var_name [, var_name] ...

4.CLOSE 光标

CLOSE cursor_name ;

示例

create table emp
(
    id     int(11)     not null auto_increment,
    name   varchar(50) not null comment '姓名',
    age    int(11) comment '年龄',
    salary int(11) comment '薪水',
    primary key (`id`)
) engine = innodb
  default charset = utf8;

insert into emp(id, name, age, salary)
values (null, '金毛狮王', 55, 3800),
       (null, '白眉鹰 王', 60, 4000),
       (null, '青翼蝠王', 38, 2800),
       (null, '紫衫龙王', 42, 1800); 
-- 查询emp表中数据, 并逐行获取进行展示
create procedure pro_test11()
begin
    declare e_id int(11);
    declare e_name varchar(50);
    declare e_age int(11);
    declare e_salary int(11);
    declare emp_result cursor for select * from emp;

    open emp_result;

    fetch emp_result into e_id,e_name,e_age,e_salary;
    select concat('id=', e_id, ', name=', e_name, ', age=', e_age, ', 薪资为: ', e_salary);

    fetch emp_result into e_id,e_name,e_age,e_salary;
    select concat('id=', e_id, ', name=', e_name, ', age=', e_age, ', 薪资为: ', e_salary);

    fetch emp_result into e_id,e_name,e_age,e_salary;
    select concat('id=', e_id, ', name=', e_name, ', age=', e_age, ', 薪资为: ', e_salary);

    fetch emp_result into e_id,e_name,e_age,e_salary;
    select concat('id=', e_id, ', name=', e_name, ', age=', e_age, ', 薪资为: ', e_salary);

    fetch emp_result into e_id,e_name,e_age,e_salary;
    select concat('id=', e_id, ', name=', e_name, ', age=', e_age, ', 薪资为: ', e_salary);

    close emp_result;

end

通过循环结构 , 获取游标中的数据 :

DELIMITER $
create procedure pro_test12()
begin
    DECLARE id int(11);
    DECLARE name varchar(50);
    DECLARE age int(11);
    DECLARE salary int(11);
    DECLARE has_data int default 1;
    
    DECLARE emp_result CURSOR FOR select * from emp;
    DECLARE EXIT HANDLER FOR NOT FOUND set has_data = 0;

    open emp_result;

    repeat
        fetch emp_result into id , name , age , salary;
        select concat('id为', id, ', name 为', name, ', age为 ', age, ', 薪水为: ',salary);
    until has_data = 0
        end repeat;

    close emp_result;
    
end$
DELIMITER ; 

7. 存储函数

1.语法结构:

CREATE FUNCTION function_name([param type ... ]) 
RETURNS type 
BEGIN

    ... 

END; 

2.案例 :

定义一个存储过程, 请求满足条件的总记录数 ;

delimiter $
create function count_city(countryId int)
    returns int
begin

    declare cnum int;
    select count(*) into cnum from city where country_id = countryId;
    return cnum;

end$
delimiter ;

调用:

select count_city(1); select count_city(2);
上一篇下一篇

猜你喜欢

热点阅读