美文网首页
MySQL存储过程和函数(2)

MySQL存储过程和函数(2)

作者: 李白开水 | 来源:发表于2020-06-30 21:48 被阅读0次

    语法

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

    1.变量

    变量的定义

    语法:

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

    var_name:变量名
    type:变量类型
    DEFAULT value:默认值
    创建存储过程:


    image.png

    调用存储过程:


    image.png

    变量的赋值

    1.使用SET

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

    可以赋常量或者赋表达式。

    创建存储过程:


    image.png

    调用存储过程:


    image.png

    2.使用select ... into
    将查询的结果赋值给变量
    创建存储过程:


    image.png

    调用存储过程:


    image.png

    2.if条件判断

    语法:

    if search_condition then statement_list
    [elseif search_condition then statement_list] ...
    [else statement_list]
    end if;
    

    举例:

    根据定义的分数,判定当前分数的所属的类型
    85 及以上 ----------> 优秀
    60-90 ---------> 及格
    60以下 ----------> 不及格

    创建存储过程:

    create procedure pro_test4()
    begin
    declare my_score int default 85;
    declare description varchar(50);
    if my_score >= 85 then
    set description = '优秀';
    elseif my_score >= 60 and my_score < 85 then
    set description = '及格';
    else
    set description = '不及格';
    end if;
    select description ;
    end$
    
    image.png

    调用存储过程:


    image.png

    3.传递参数

    语法:

    create procedure procedure_name([in/out/inout] 参数名 参数类型)
    ...
    IN : 该参数可以作为输入,也就是需要调用方传入值 , 默认
    OUT: 该参数作为输出,也就是该参数可以作为返回值
    INOUT: 既可以作为输入参数,也可以作为输出参数
    

    IN 输入参数

    默认为输入参数
    创建存储过程:

    create procedure pro_test5(in my_score int)
    begin
    declare description varchar(50);
    if my_score >= 85 then
    set description = '优秀';
    elseif my_score >= 60 and my_score < 85 then
    set description = '及格';
    else
    set description = '不及格';
    end if;
    select description ;
    end$
    
    image.png

    调用存储过程,需要传递一个参数:


    image.png

    OUT 输出参数

    需求:
    根据传入的分数变量,获取当前身高的所属的分数类型
    创建存储过程:

    create procedure pro_test6(in my_score int , out description varchar(100))
    begin
    if my_score>= 85 then
    set description='优秀';
    elseif my_score >= 60 and my_score < 85 then
    set description='及格';
    else
    set description='不及格';
    end if;
    end$
    
    image.png

    调用存储过程:


    image.png
    image.png

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

    4.case结构

    语法一:

    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;
    

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

    创建存储过程:

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

    调用存储过程:


    image.png

    5.while循环

    语法:

    while search_condition do
    statement_list
    end while;
    

    创建存储过程:

    create procedure pro_test02(n int)
    begin
    declare my_sum int default 0;
    declare num int default 0;
    while num < n do
    set my_sum = my_sum + num;
    set num = num + 1;
    end while;
    select concat('您输入的值为:',num,'总和为:',my_sum) as content;
    end$
    
    image.png

    调用存储过程:


    image.png

    6.repeat结构

    语法:

    REPEAT
    statement_list
    UNTIL search_condition
    END REPEAT;
    

    注意:until后面条件结束后没有分号
    创建存储过程:

    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$
    
    image.png

    调用存储结构:


    image.png

    7.loop语句

    语法:

    [begin_label:] LOOP
    statement_list
    END LOOP [end_label]
    

    可以看出上面的loop循环中没有退出循环的条件,所以loop退出循环一一般用leave语句来实现。

    8.leave语句

    需求:从1加到n

    create procedure pro_test3(in n int) 
    begin
    declare my_sum int default 0;         
    ins: loop
    if n<= 0 then 
    leave ins;
    end if;
    set my_sum = my_sum + n;
    set n = n - 1;
    end loop ins;
    select my_sum;
    end$
    

    创建存储过程:


    image.png

    调用存储过程:


    image.png

    9.游标/光标

    游标(Cursor)是处理数据的一种方法,为了查看或者处理结果集中的数据,游标提供了在结果集中一次一行或者多行前进或向后浏览数据的能力。

    语法:
    声明光标:

    DECLARE cursor_name CURSOR FOR select_statement ;
    

    OPEN 光标:

    OPEN cursor_name ;
    

    FETCH 光标:

    FETCH cursor_name INTO var_name [, var_name] ...
    

    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);
    

    如图所示:


    image.png

    查看表中的数据:


    image.png

    查询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$
    
    image.png

    调用:


    image.png

    这样的话,不仅每一条都要写fetch语句,而且如果游标fetch移到没有数据的位置,还会报错。
    改进方法是使用循环来fetch,并且要标记表中是否还有数据,如果没有,结束当前的查询。

    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;
    # 如果取不到数据,那么把has_data这个变量置为0
    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$
    
    image.png

    其中DECLARE EXIT HANDLER FOR NOT FOUND set has_data = 0;为声明异常处理的语句。
    语法:

    DECLARE
    {EXIT | CONTINUE}
    HANDLER FOR
    {error-number | SQLSTATE error-string | condition}
    SQL statement
    
    • Handler Type (CONTINUE,EXIT)//处理类型 继续或退出
    • Handler condition (SQLSTATE,MYSQL ERROR,CONDITION)//触发条件
    • Handler actions(错误触发的操作)

    调用:


    image.png

    10.存储函数

    存储函数和存储过程的区别在于,存储函数必须有返回值,存储过程可以有也可以没有。
    存储函数可以实现的功能,存储函数也可以做。
    语法:

    CREATE FUNCTION function_name([param type ... ])
    # 生命返回值类型
    RETURNS type
    BEGIN
    ...
    END;
    

    先查看一下city表:


    image.png

    创建存储函数,求满足条件的总记录数:

    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$
    
    image.png

    调用:
    调用使用select语句:


    image.png

    使用call会报错:


    image.png
    删除使用:
    drop function + 函数名;
    
    image.png

    相关文章

      网友评论

          本文标题:MySQL存储过程和函数(2)

          本文链接:https://www.haomeiwen.com/subject/uviofktx.html