The first use of stored procedures cursor pit encountered

The first use of stored procedures cursor pit encountered

  There is such a demand: a city of a province before enumeration district six months of data, direct sql query efficiency is very low, he intended to do regular tasks, timer mode with the stored procedure execution statistics data last month at the beginning of each month.

  Using stored procedures necessary to use the cursor, before seldom write stored procedures, cursors are not familiar with, we supposed to do, off now friends.

Create a stored procedure

 1 CREATE
 2     [DEFINER = { user | CURRENT_USER }]
 3  PROCEDURE sp_name ([proc_parameter[,...]])
 4     [characteristic ...] routine_body
 5  
 6 proc_parameter:
 7     [ IN | OUT | INOUT ] param_name type
 8  
 9 characteristic:
10     COMMENT 'string'
11   | LANGUAGE SQL
12   | [NOT] DETERMINISTIC
13   | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
14   | SQL SECURITY { DEFINER | INVOKER }
15  
16 routine_body:
17   Valid SQL routine statement
18  
19 [begin_label:] BEGIN
20   [statement_list]
21     ……
22 END [end_label]

The key grammar MYSQL stored procedure

Disclaimer statement terminator, you can customize:

1 DELIMITER $$
2 3 DELIMITER //

Statement stored procedure:

1 CREATE PROCEDURE demo_in_parameter(IN p_in int)

Stored procedures start and end symbols:

1 BEGIN .... END

Variable assignment:

1 SET @p_in=1

Variable definitions:

1 DECLARE l_int int unsigned default 0;

Create a mysql stored procedures, stored functions:

1  the Create  Procedure stored procedure name (parameters)

Body of the procedure:

. 1  Create  function storage function name (parameter)

cursor

Brief introduction

    Each time a record extraction mechanism comprising a cursor is actually a plurality of data records from the result set.

    The role of acting as a cursor pointer.

    Although the cursor can traverse all the rows in the result, but he only pointed a row.

Role of the cursor is used to query the database records returned by traversing, in order to perform the corresponding operation.

usage

    一、声明一个游标: declare 游标名称 CURSOR for table;(这里的table可以是查询出来的任意集合)
    二、打开定义的游标:open 游标名称;
    三、获得下一行数据:FETCH  游标名称 into testrangeid,versionid(和查出的字段顺序保持一致);
    四、需要执行的语句(增删改查):这里视具体情况而定
    五、释放游标:CLOSE 游标名称;
   注:mysql存储过程每一句后面必须用;结尾,使用的临时字段需要在定义游标之前进行声明。

先写之前出现的错误写法:

  这样写出的双重循环,里面的会执行6次,外层只会执行一次,如果在后面把done置为0就会出现死循环。 

 1 CREATE DEFINER=`root`@`%` PROCEDURE `p_month_count_init`()
 2 BEGIN 
 3             
 4             -- 定义变量
 5             DECLARE done int DEFAULT 0;
 6             declare i int DEFAULT 0;
 7             declare v_yearMonth varchar(6);
 8             declare v_provinceCode varchar(50) default '';--
 9             declare v_cityCode varchar(50) default '';--
10 
11             -- 定义游标,并将sql结果集赋值到游标中
12             DECLARE cur CURSOR FOR 
13                 select province_code,city_code from dt_lift_info where is_delete = 0 group by province_code,city_code;
14             -- 声明当游标遍历完后将标志变量置成某个值
15             DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
16             -- 打开游标
17             open cur;
18             
19                     fetch cur into v_provinceCode,v_cityCode;
20                     -- 当done不等于1,也就是未遍历完时,会一直循环
21                     while done<>1 do
22                             while i<6 DO -- 循环开始
23                                 set i=i+1;
24                                 set v_yearMonth = DATE_FORMAT( DATE_SUB(CURDATE(), INTERVAL i MONTH), '%Y%m');
25                                 call p_month_count(v_yearMonth,v_provinceCode,v_cityCode);
26                             end while; -- 循环结束
27                             -- 将游标中的值再赋值给变量,供下次循环使用
28                             fetch cur into v_provinceCode,v_cityCode;
29                     -- 当s等于1时表明遍历以完成,退出循环
30                     end while;
31             -- 关闭游标
32             close cur;
33     END
  最后改成这样写就可以了。
 1 CREATE DEFINER=`root`@`localhost` PROCEDURE `p_month_count_init`()
 2     BEGIN 
 3             -- 定义变量
 4             DECLARE done int DEFAULT 0;
 5             declare i int DEFAULT 0;
 6             declare v_yearMonth varchar(6);
 7             declare v_provinceCode varchar(50) default '';--
 8             declare v_cityCode varchar(50) default '';--
 9             declare v_areaCode varchar(50) default '';--
10 
11             -- 定义游标,并将sql结果集赋值到游标中
12             DECLARE cur CURSOR FOR 
13                 select province_code,city_code,area_code from dt_lift_info where is_delete = 0 group by province_code,city_code,area_code;
14             -- 声明当游标遍历完后将标志变量置成某个值
15             DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
16             
17             first_loop:LOOP
18                 IF i >= 6 THEN
19                     LEAVE first_loop;
20                 END IF;
21                 set i=i+1;
22                 set v_yearMonth = DATE_FORMAT( DATE_SUB(CURDATE(), INTERVAL i MONTH), '%Y%m');
23                 -- 打开游标
24                 open cur;
25                     second_loop:LOOP
26                         fetch cur into v_provinceCode,v_cityCode,v_areaCode;
27                         IF done = 1 THEN
28                             LEAVE second_loop;
29                         END IF;
30                         call p_month_count(v_yearMonth,v_provinceCode,v_cityCode,v_areaCode);
31                     end LOOP second_loop;
32                 SET done = 0; -- 注意这个别漏了
33                 -- 关闭游标
34                 close cur;
35             END LOOP first_loop;
36     END

  做完这个存储过程之后,瞬间感觉对存储过程理解的深了一点。

Guess you like

Origin www.cnblogs.com/xyy2019/p/11783006.html