MySQL 存储过程

本文详细介绍了MySQL数据库的存储过程,包括创建、调用、变量使用、流程控制(如IF、CASE、LOOP、REPEAT、WHILE)、游标及异常处理。内容涵盖基本语法、参数类型、局部和用户变量、流程控制结构以及游标的声明和操作。同时,展示了如何在存储过程中进行条件判断和循环控制,并提供了实例代码和解释。
摘要由CSDN通过智能技术生成

【黑马程序员】两小时带你玩转MySQL数据库存储过程【配套源码+笔记】_哔哩哔哩_bilibili

一、语法

delimter $$ 

声明结束符。因为MySQL 默认使用“;”作为结束符,而在存储过程中,会使用“;”作为一段语句的结束,导致“;”使用冲突。

1. 语法结构

CREATE

        [DEFINER = user]

        PROCEDURE sp_name ( [ proc_parameter[...] ] )

        [chrarcteristic ... ] routine_body

-- proc_parameter 参数部分,可以如下书写:

        [ IN | OUT | INOUT ] param_name type

        -- type 类型可以是 MySQL 支持的所有类型

-- routine_body(程序体)部分,可以书写合法的 SQL 语句

        BEGIN ... END

简单演示:

delimiter $$

CREATE PROCEDURE hello_procedure()
BEGIN
    select * from users;
END $$

使用:

call hello_procedure();

2. 变量及赋值

类比一下 java 中的局部变量和成员变量的声明和使用

(1)局部变量

用户自定义,在 begin/end 块中有效

语法:

声明变量: declare var_name type [ default var_value ];

举例:declare nickname varchar(32);

-- set 赋值

delimiter $$

create procedure sp_var01()
begin
    declare nickname varchar(32) default 'unkown';
    set nickname = 'ZS';
    select nickname;
end $$

 -- into 赋值

delimiter $$

create procedure sp_var_into()
begin
    declare emp_name varchar(32) default 'unkown';
    declare emp_no int default 0;
    select e.empno,e.ename into emp_no,emp_name from emp e where e.empno = 7839;
    select emp_no,emp_name ;
end $$

(2)用户变量

用户自定义,当前会话(连接)有效

  --  赋值

delimiter $$

create procedure sp_var02()
begin
    set @nickname = 'ZS';
end $$

call sp_var02() $$
select @nickname $$

(3)会话变量

 由系统提供,当前会话(连接)有效

语法:

@@session.var_name

举例:

-- 查看会话变量
show session variables;
-- 查看某会话变量
select @@session.unique_checks;
-- 修改会话变量
set @@session.unique_checks = 0;

(4)全局变量

  由系统提供,整个 mysql 服务器有效

语法:

@@global.var_name

举例:

-- 查看全局变量中变量名有char的记录
show global variables like '%char%';

-- 查看全局变量character_set_client的值
select @@global.character_set_client;

3. 入参出参

-- 语法

in | out | inout  param_name type

(1)-- IN 类型演示

delimiter $$

create procedure sp_param01(in age int)
begin
    set @user_age = age;
end $$

call sp_param01(10) $$
select @user_age $$

 (2)-- OUT 类型演示,只负者输出

delimiter $$

create procedure sp_param02(in loc varchar(64),out dedpt_no int(11))
begin
    select d.deptno into dept_no from dept d where d.loc = loc;
end $$

-- 测试
set @dept_no = 100;
call sp_param02('DALLAS',@dept_no); $$
select @dept_no; $$

  (3)-- INOUT 类型 

delimiter $$

create procedure sp_param03(inout name varchar)
begin
    select name = concat('hello',name);
end $$

-- 测试
set @username = '小妹';
call sp_param03(@username);
select @user_name;

4. 流程控制-判断

(1)if

语法:

IF search_condition THEN statement_list

        [ ELSEIF search_condition THEN  statement_list ] ...

        [ ELSE statement_list ]

END IF

前置知识点:timestampdiff( unit,exp1,exp2-) 取差值exp2-exp1 差值,单位是 unit

select timestampdiff( year,e.hiredate,now() ) from emp e where e.empno = '7499';

delimiter $$

create procedure sp_hire_if()
begin
    declare result varchar(32);
    if timestampdiff(year,'2001-01-01',now()) > 40
        then set result = '元老';
    elseif timestampdiff(year,'2001-01-01',now()) > 35
        then set result = '老员工';
    else
        set result = '新手';
    end if;
    select result;
end $$

(2)case

语法一:(类比 java 的 switch)

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 search_condition ]

END CASE

5. 流程控制-循环

(1)loop

语法:

[ begin_label : ] LOOP

        statement_list 

END IOOP [ end_label ]

注意:

loop 是死循环,需要手动退出循环,可以把 leave 看成 java 中的 break;iterate(继续循环)看成 java 中的 continue。

leave 控制循环的退出

delimiter $$

create procedure sp_flow_loop()
begin
    declare c_index int default 1;

    num_loop:loop

        select c_index;
        if c_index >= 10
        then leave num_loop;
        end if;

        set c_index = c_index + 1;

    end loop num_loop;
    
end $$

 iterate + leave 控制循环

delimiter $$

create procedure sp_flow_loop02()
begin
    declare c_index int default 1;
    declare result_str varchar(256) default '1';

    cnt:loop

        set c_index = c_index + 1;
        set result_str = concat(result_str ,c_index);

        
        if c_index < 10 then iterate cnt;
        end if;

        leave cnt;

    end loop cnt;
    select result_str;
end $$

(1)repeat

[ begin_label : ] REPEAT

        statement_list 

UNTIL search_condition          -- 直到。。。为止

END REPEAT [ end_label ]

delimiter $$

create procedure sp_flow_repeat()
begin
    declare c_index int default 1;
    declare result_str varchar(256) default '1';

    count_lab:repeat

        set c_index = c_index + 1;
        set result_str = concat(result_str ,c_index);
        until c_idnex >= 10
        
    end repeat count_lab;
    select result_str;
end $$

(1)while

[ begin_label : ] WHILE  search_condition DO         

        statement_list 

END WHILE  [ end_label ]

delimiter $$

create procedure sp_flow_while()
begin
    declare c_index int default 1;
    declare result_str varchar(256) default '1';

    while  c_idnex < 10 do
        set c_index = c_index + 1;
        set result_str = concat(result_str ,c_index);

    end while;
    select result_str;
end $$

6. 流程控制-退出、继续循环

leave 看成 java 中的 break;iterate(继续循环)看成 java 中的 continue。

7. 游标

类比 jdbc 的 ResultSet

-- 声明语法

DECLARE cursor_name CURSOR FOR select_statement

-- 打开语法

OPEN cursor_name

-- 取值语法

FETCH cursor_name INTO var_name [ ,var_name ] ...

-- 关闭语法

CLOSE cursor_name

需求:按照部门名称查询员工,通过 select 查看员工的编号、姓名、薪资

delimiter $$

create procedure sp_create_table02(in dept_name varchar(32))
begin
    declare emp_no int;
    declare emp_name varchar(32);
    declare emp_sal decimal(7,2);
    declare exit_flag int default 0;

    declare emp_cursor cursor for
        select e.empno,e.ename,e.sal
        from emp e inner join dept d on e.deptno = d.deptno
        where d.dname = dept_name;

    declare continue handler for not found set exit_flag = 1;

    open emp_cursor;

    c_loop:loop

        fetch emp_cursor into emp_no ,emp_name ,emp_sal ;

        if exit_flag != 1    
            select emp_no ,emp_name ,emp_sal ;
            -- ITERATE c_loop;
        else
            then leave c_loop;
        end if;

    end loop c_loop;

    select @sex_res;
    close emp_cursor;

end $$

注意 :在语法中,变量声明、handler 声明是必须按照先后顺序书写的,否则创建存储过程出错。

8. 存储过程中的 handler

 DECLARE handler_action HANDLER

        FOR condition_value [ , condition_value ] ...

        statement

handler_action:{

        CONTINUE

        | EXIT

        | UNDO

condition_value:{

        mysql_error_code

        | SQLSTATE [ VALUE ] sqlstate_value

        | condition_name

        | SQLWARING

        | NOT FOUND

        | SQLEXCEPTION

SQLWARING:Shorthand for the class of SQLSTATE values that begin whit '01'(以“01”开头的SQLSTATE值类的缩写)

NOT FOUND:Shorthand for the class of SQLSTATE values that begin whit '02'

SQLEXCEPTION:Shorthand for the class of SQLSTATE values that do not begin whit '00','01',or'02'(不以“00”、“01”、“02”开头的SQLSTATE值类的缩写)

对于游标遍历到尽头时的错误码处理,我们可以使用:

Error number: 1329 ; Symbol:ER_SP_PETCH_NO_DATA; SQLSTATE: 02000
Message: No data - zero rows fetched,selected, or processed

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值