存储过程

举报
Nick Qiu 发表于 2020/10/23 12:51:18 2020/10/23
【摘要】 介绍存储过程是一种sql的语句集,其优点如下:灵活,比sql更加灵活;减少流量,调用存储过程会减少应用与数据库服务器之间通讯流量及时间 ;相对批量执行来说,有更高的执行效率;使用语法DROP PROCEDURE IF EXISTS `过程名`;CREATE PROCEDURE 过程名([[IN|OUT|INOUT] 参数名 数据类型[,[IN|OUT|INOUT] 参数名 数据类型…]])...

介绍

存储过程是一种sql的语句集,其优点如下:

  • 灵活,比sql更加灵活;

  • 减少流量,调用存储过程会减少应用与数据库服务器之间通讯流量及时间 ;

  • 相对批量执行来说,有更高的执行效率;

使用

语法

DROP PROCEDURE IF EXISTS `过程名`;CREATE PROCEDURE  过程名([[IN|OUT|INOUT] 参数名 数据类型[,[IN|OUT|INOUT] 参数名 数据类型…]]) 过程体
  • 如下BEGIN和END之间是过程体

  • fun 过程名

  • 带一个int类型的输出参数s

DELIMITER ;;  CREATE PROCEDURE fun(OUT s int)    BEGIN
      // sql 
    ENDDELIMITER ;

简单存储过程

DROP PROCEDURE IF EXISTS `funa`;

DELIMITER ;;CREATE  PROCEDURE `funa`()BEGIN
  SELECT 1;END;;
DELIMITER ;CALL funa() ;
  • 如上定义了一个存储过程funa,并且调用了该存储过程;

  • DELIMITER 定义语句的结束符号;

带输入参数

# defineDROP PROCEDURE IF EXISTS `funa`;

DELIMITER ;;
CREATE PROCEDURE funa(IN p int)  BEGIN
    SELECT p;  END;
;;
DELIMITER ;# callSET @p=1;
CALL funa(@p);

参数输出

# define DROP PROCEDURE IF EXISTS `funa`;
DELIMITER ;;
CREATE PROCEDURE funa(OUT p_out int)  BEGIN
    SELECT p_out;
    SET p_out=2;
    SELECT p_out;  END;
;;
DELIMITER ;# callSET @p_out=1;
CALL funa(@p_out);
SELECT @p_out;
  • 如上,执行可以发现第一个到第三个select 分别返回null,2,2,可见参数可以返回输出到类型外;

输入输出

# define DROP PROCEDURE IF EXISTS `funa`;
DELIMITER ;;
CREATE PROCEDURE funa(INOUT p_out int)  BEGIN
    SELECT p_out;
    SET p_out=2;
    SELECT p_out;  END;
;;
DELIMITER ;# callSET @p_out=1;
CALL funa(@p_out);
SELECT @p_out;
  • 如上,执行可以发现第一个到第三个select 分别返回1,2,2,可见外部参数可输入到函数内,并且参数可以返回输出到类型外;

变量

  • 变量声明,语法:DECLARE 变量名1[,变量名2...] 数据类型 [默认值];

  • 变量类型支持mysql的所有变量

  • 变量赋值,语法:SET 变量名 = 变量值 [,变量名= 变量值 ...]

  • 用户变量: 用户变量一般以@开头,因为用户变量为全局的变量,所以建议少使用用户变量

# define DROP PROCEDURE IF EXISTS `funa`;
DELIMITER ;;CREATE PROCEDURE funa()
  BEGIN
      DECLARE a1 int default 12;
        SELECT  a1;
        SET a1=13;
        SELECT  a1;
  END;
;;
DELIMITER ;# callCALL funa();

程序逻辑

条件(IF-THEN-ELSE语句)

#条件语句IF-THEN-ELSEDROP PROCEDURE IF EXISTS proc;
DELIMITER ;;
CREATE PROCEDURE proc(IN parameter int)
  BEGIN    DECLARE var int;
    SET var=parameter+1;    IF var=0 THEN
       SELECT 0;
    END IF ;    IF parameter=0 THEN
      select "=0";    ELSE
      select ">0";
    END IF ;
  END ;
  ;;
DELIMITER ;

call proc(-1);

CASE-WHEN-THEN-ELSE语句

DROP PROCEDURE IF EXISTS proc;
DELIMITER ;;
  CREATE PROCEDURE proc (IN param INT)
    BEGIN      CASE param
        WHEN 0 THEN
          SELECT 0;
        WHEN 1 THEN
           SELECT 1;        ELSE
           SELECT 1;
      END CASE ;
    END ;
  ;;
DELIMITER ;
CALL proc(1)

循环语句

# WHILE-DO…END-WHILEDROP PROCEDURE IF EXISTS proc;
DELIMITER ;;
  CREATE PROCEDURE proc()
    BEGIN      DECLARE var INT;
      SET var=0;      WHILE var<6 DO
        SELECT var;
        SET var=var+1;
      END WHILE ;
    END;
  ;;
DELIMITER ;
call proc();
# REPEAT...END REPEAT# 此语句的特点是执行操作后检查结果DROP PROCEDURE IF EXISTS proc;
DELIMITER ;;
  CREATE PROCEDURE proc ()    BEGIN
      DECLARE v INT;
      SET v=0;
      REPEAT
        SELECT v;
        SET v=v+1;
        UNTIL v>=5
      END REPEAT;    END;
  ;;
DELIMITER ;
call proc();
# LOOP...END LOOPDROP PROCEDURE IF EXISTS proc;
DELIMITER ;;
  CREATE PROCEDURE proc ()
    BEGIN      DECLARE v INT;
      SET v=0;
      LOOP_LABLE:LOOP
        SELECT v;
        SET v=v+1;        IF v >=5 THEN
          LEAVE LOOP_LABLE;
        END IF;
      END LOOP;
    END;
  ;;
DELIMITER ;
call proc();

应用

游标遍历select结果

DROP TABLE IF EXISTS `tbl_job`;
CREATE TABLE `tbl_job` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `JOB_NAME` varchar(32) NOT NULL COMMENT '职位名称',
  `OCCUPANT_ID` int(11) NOT NULL COMMENT '任职者',
  `AGE` int(11) NOT NULL COMMENT '年龄',
  PRIMARY KEY (`ID`)
);
-- ----------------------------
-- Records of tbl_job
-- ----------------------------
INSERT INTO `tbl_job` VALUES ('1', '经理', '1', '21'),
('2', '董事长', '2', '21'),
('3', '项目组长', '3', '22'),
('4', 'SE', '4', '24'),
('5', 'MDE', '5', '24');

DROP PROCEDURE IF EXISTS proc_tbl_job;
DELIMITER ;;
CREATE PROCEDURE proc_tbl_job(IN inId INT)
BEGIN    DECLARE id INT;    DECLARE jobName VARCHAR(32);    DECLARE occupantId INT;    DECLARE age INT;    
    DECLARE done INT DEFAULT FALSE;    DECLARE curJob CURSOR FOR ( -- 定义
        SELECT ID,JOB_NAME,OCCUPANT_ID,AGE FROM tbl_job -- WHERE ID = inId
    );    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; -- 监听器
    
    OPEN curJob; -- 打开游标
    label:LOOP
        FETCH curJob INTO id,jobName,occupantId,age;        IF done THEN LEAVE label;END IF;
        SELECT id,jobName,occupantId,age;
    END LOOP label;
    
    CLOSE curJob; -- 关闭游标
END ;;
delimiter;
 
CALL proc_tbl_job(2)

复杂嵌套

DROP PROCEDURE IF EXISTS proc_syn_single_blacklist;
DELIMITER ;;
CREATE PROCEDURE proc_syn_single_blacklist(IN var_license VARCHAR(10))
BEGIN    DECLARE var_calc_amount_owed INT DEFAULT 0;  
    DECLARE var_calc_paid_in_money INT DEFAULT 0;    DECLARE var_calc_arrears_count INT DEFAULT 0;
    
    SELECT License ,IFNULL(SUM(ReceivablesMoney),0),IFNULL(SUM(PaidInMoney),0),IFNULL(COUNT(*),0)
        into var_license, var_calc_amount_owed,var_calc_paid_in_money,var_calc_arrears_count
            FROM  urpcs_evasion_arrears WHERE  license=var_license;
    SELECT var_license,var_calc_amount_owed,var_calc_paid_in_money,var_calc_arrears_count;
END ;;
DELIMITER;

DROP PROCEDURE IF EXISTS proc_syn_blacklist;
DELIMITER ;;
CREATE PROCEDURE proc_syn_blacklist()
BEGIN    DECLARE var_license VARCHAR(10);    DECLARE done INT DEFAULT FALSE;    DECLARE curJob CURSOR FOR ( -- 定义
        SELECT DISTINCT license  FROM  urpcs_evasion_arrears ORDER BY EvasionID LIMIT 2 
    );    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; -- 监听器
    
    OPEN curJob; -- 打开游标
    label:LOOP
        FETCH curJob INTO var_license;        IF done THEN LEAVE label;END IF;
                call proc_syn_single_blacklist(var_license);
    END LOOP label;
    
    CLOSE curJob; -- 关闭游标
END ;;
DELIMITER;

 
CALL proc_syn_blacklist();


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。