您当前的位置: 首页 >  sql

Charge8

暂无认证

  • 2浏览

    0关注

    447博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

MySQL存储过程入门

Charge8 发布时间:2018-12-02 23:17:13 ,浏览量:2

 

#SQL语句:先编译后执行

存储过程(Stored Procedure):

  一组可编程的函数,是为了完成特定功能的SQL语句集,经编译创建并保存在数据库中,用户可通过指定存储过程的名字并给定参数(需要时)来调用执行。

优点(为什么要用存储过程?):

  1)将重复性很高的一些操作,封装到一个存储过程中,简化了对这些SQL的调用

  2)批量处理:SQL+循环,减少流量

  3)统一接口,确保数据的安全

缺点:

       1)不同数据库,语法差别很大,移植困难,换了数据库,需要重新编写;

       2)不好管理,把过多业务逻辑写在存储过程不好维护,不利于分层管理,容易混乱,一般存储过程适用于个别对性能要求较高的业务,其它的必要性不是很大;

相对于oracle数据库来说,MySQL的存储过程相对功能较弱,使用较少。

 

一、存储过程的创建和调用

  存储过程就是具有名字的一段代码,用来完成一个特定的功能。

  创建的存储过程保存在数据库的数据字典中。

1、创建存储过程语法

CREATE
    [DEFINER = { user | CURRENT_USER }]
 PROCEDURE sp_name ([proc_parameter[,...]])
    [characteristic ...] routine_body

proc_parameter:
    [ IN | OUT | INOUT ] param_name type

characteristic:
    COMMENT 'string'
  | LANGUAGE SQL
  | [NOT] DETERMINISTIC
  | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
  | SQL SECURITY { DEFINER | INVOKER }

routine_body:
  Valid SQL routine statement

[begin_label:] BEGIN
  [statement_list]
    ……
END [end_label]

简单点:create procedure 存储过程的名字(参数列表) begin 存储过程体(SQL语句的集合); end

注意:参数列表包含三个部分: 参数模式 参数名 参数类型     参数模式: in , out, inout .  (比如: in s_name varchar(20) )

    DELIMITER $$  自定义结束符$$,替换成;;。

    DEFINER  存过创建者;

案例:创建一个存储过程,删除给定学生的信息

DROP PROCEDURE IF EXISTS `proc_adder`;
DELIMITER ;;
CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_adder`(IN a int, IN b int, OUT sum int)
BEGIN
    #Routine body goes here...

    DECLARE c int;
    if a is null then set a = 0; 
    end if;
  
    if b is null then set b = 0;
    end if;

    set sum  = a + b;
END
;;
DELIMITER ;   #将语句的结束符号恢复为分号

    

解析:

  在定义过程时,使用DELIMITER ;; 命令将语句的结束符号从分号 ; 临时改为两个;;,使得过程体中使用的分号被直接传递到服务器,而不会被客户端(如mysql)解释。

2、调用存储过程:call 存过名[(传参)];

mysql> call pro_student(22);
Query OK, 1 row affected (0.03 sec)

3、存储过程体

  存储过程体包含了在过程调用时必须执行的语句,例如:dml、ddl语句,if-then-else和while-do语句、声明变量的declare语句等

  过程体格式:以begin开始,以end结束(可嵌套)

BEGIN
  BEGIN
    BEGIN
      statements; 
    END
  END
END

注意:每个嵌套块及其中的每条语句,必须以分号结束,表示过程体结束的begin-end块(又叫做复合语句compound statement),则不需要分号。

4、为语句块贴标签

[begin_label:] BEGIN
  [statement_list]
END [end_label]

例如:

label1: BEGIN
  label2: BEGIN
    label3: BEGIN
      statements; 
    END label3 ;
  END label2;
END label1

标签有两个作用:

  1)增强代码的可读性

  2)在某些语句(例如:leave和iterate语句),需要用到标签

5、删除存储过程

     drop procedure 存储过程名 ; 

 

二、存储过程的参数

  存储过程可以有0个或多个参数,用于存储过程的定义。

3种参数类型:

  IN 输入参数:表示调用者向过程传入值(传入值可以是字面量或变量)

  OUT 输出参数:表示过程向调用者传出值(可以返回多个值)(传出值只能是变量)

  INOUT 输入输出参数:既表示调用者向过程传入值,又表示过程向调用者传出值(值只能是变量)

建议:

  输入值使用 in 参数;

  返回值使用 out 参数;

  inout 参数就尽量的少用。

1、in 输入参数

mysql> delimiter $$  #将语句的结束符号从分号;临时改为两个$$(可以是自定义)
mysql> CREATE PROCEDURE pro_student(IN p_id INTEGER(11))
    -> BEGIN
    ->   DELETE FROM student
    ->     WHERE id= p_id;
    -> END$$
Query OK, 0 rows affected (0.01 sec)

mysql> delimiter ;  #将语句的结束符号恢复为分号

mysql> call pro_student(22) ;   #调用存过

2、out输出参数

案例:根据学生姓名,返回对应的年龄和学生编号

mysql> delimiter $$  
mysql> CREATE PROCEDURE pro_student(in sname varchar(10),out age int,out sid int)
    -> BEGIN
    ->   select a.age ,s.id into age,sid
    ->     from students s
    ->         inner join ages a
    ->         on s.age_id = a.id
    ->    where s.sname=sname;
    -> END$$
Query OK, 0 rows affected (0.01 sec)

mysql> delimiter ;  #将语句的结束符号恢复为分号

mysql> call('admin',@age,@sid) ;   #调用存过

mysql> select @age,@sid ; 

3、inout输入参数

mysql> delimiter $$
mysql> create procedure pro_param(inout p_inout int)
    -> begin
    ->     set p_inout=p_inout*2;
    -> end $$

mysql> delimiter ;

mysql> set @p_inout=1;

mysql> call pro_param(@p_inout);

mysql> select @p_inout;

 

注意:存过中的参数为局部变量、@参数名为全局变量。

三、存储过程中的控制语句

1、IF语句:

DROP PROCEDURE IF EXISTS `proc_if`;
DELIMITER ;;
CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_if`(IN type int)
BEGIN
    #Routine body goes here...
    DECLARE c varchar(500);
    IF type = 0 THEN
        set c = 'param is 0';
    ELSEIF type = 1 THEN
        set c = 'param is 1';
    ELSE
        set c = 'param is others, not 0 or 1';
    END IF;
    select c;
END
;;
DELIMITER ;

    

2、CASE语句:

DROP PROCEDURE IF EXISTS `proc_case`;
DELIMITER ;;
CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_case`(IN type int)
BEGIN
    #Routine body goes here...
    DECLARE c varchar(500);
    CASE type
    WHEN 0 THEN
        set c = 'param is 0';
    WHEN 1 THEN
        set c = 'param is 1';
    ELSE
        set c = 'param is others, not 0 or 1';
    END CASE;
    select c;
END
;;
DELIMITER ;

    

3、循环while语句:

DROP PROCEDURE IF EXISTS `proc_while`;
DELIMITER ;;
CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_while`(IN n int)
BEGIN
    #Routine body goes here...
    DECLARE i int;
    DECLARE s int;
    SET i = 0;
    SET s = 0;
    WHILE i             
关注
打赏
1664721914
查看更多评论
0.0410s