一、环境
数据库:mysql8.0.25 社区版
操作系统:windows 11
————————————
二、创建日历表
CREATE TABLE `sys_calendar` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `day_date` datetime DEFAULT NULL, `year_num` int DEFAULT NULL, `month_num` int DEFAULT NULL, `day_num` int DEFAULT NULL, `day_str` varchar(10) DEFAULT NULL, `day_int` int DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
三、创建存储过程
DROP PROCEDURE IF EXISTS sp_createcalendar;
DELIMITER $$
CREATE PROCEDURE `spring`.`sp_createcalendar`(IN pstartyear INT ,IN pendyear INT)         
    BEGIN
        DECLARE v_msg  VARCHAR(100) DEFAULT 'good';
        
        DECLARE v_year INT DEFAULT 0;
        DECLARE v_month INT DEFAULT 0;
        DECLARE v_day INT DEFAULT 0;
        DECLARE v_day_dt DATETIME;
        DECLARE v_day_str VARCHAR(10);
        DECLARE v_day_int INT DEFAULT 0;
        DECLARE CONTINUE HANDLER FOR SQLSTATE '22007' SET v_msg='error';
        TRUNCATE TABLE sys_calendar;
        SET v_year=pstartyear;
        WHILE v_year<=pendyear DO
          SET v_month=1;
          WHILE v_month<=12 DO
             SET v_day=1;
             WHILE v_day<=31 DO             
                SET v_day_int=V_YEAR*10000+v_month*100+v_day;
                SET v_day_dt= STR_TO_DATE(v_day_int,'%Y%m%d');                
                IF (v_day_dt IS NOT NULL) THEN    
                    SET v_day_str=DATE_FORMAT(v_day_dt,'%Y/%m/%d');               
            INSERT INTO sys_calendar (
              day_date,
              year_num,
              month_num,
              day_num,
              day_str,
              day_int
            )
            VALUES
              (
                v_day_dt,
                v_year,
                v_month,
                v_day,
                v_day_str,
                v_day_int
              );                          
                END IF;
                IF @v_msg='error' THEN
                  SET v_day=32;  -- 跳出循环
                END IF;
                SET v_day=v_day+1;
             END WHILE;
             SET v_month=v_month+1;
          END WHILE;
          SET v_year=v_year+1;
        END WHILE;
    END$$
DELIMITER ;
这个过程写了好一会,大概快一个小时,时间都浪费查资料解决几个问题:
1.如何定义变量, 比过去好了
2.如何赋值和使用,比过去好了,不要再带@。要带@也可以,主要是为了向下兼容。
3.如何处理异常,和过去一样垃圾,需要实现定义异常处理,并定义异常处理的语句后面不能有declare。
稍微可以重点说的是:异常处理之后跳出本循环
 IF @v_msg='error' THEN
    SET v_day=32;  -- 跳出循环
 END IF;
以上的语句的意思是:
判断异常变量是否为’error’,如果是则设置循环变量为不满足循环条件,则会跳出本循环。
变量v_msg的值,是异常处理定义语句执行后设置的。
DECLARE CONTINUE HANDLER FOR SQLSTATE ‘22007’ SET v_msg=’error’;
上面一个语句的意思是:发生异常(错误状态为22007),则把变量设置为’error’。
四、执行存储过程
CALL sp_createcalendar(2010,2030);
查询看看结果:
SELECT * FROM sys_calendar; SELECT COUNT(*),year_num FROM sys_calendar GROUP BY year_num;


五、获取异常状态信息(SQLSTATE)
mysql有意思的是sqlstate和出现异常的提示的SQLCODE不是一个东西,徒增用户麻烦。
如果不知道异常代码是啥,那么好办,有一个办法(也许有更好的)。
以下代码参考:Mysql 获取存储过程中的异常信息 – 一叶扁舟,乘风破浪 – 博客园 (cnblogs.com)
DROP PROCEDURE IF EXISTS sp_exception;
DELIMITER $$
CREATE PROCEDURE `spring`.`sp_exception`()         
    BEGIN
          DECLARE code CHAR(5) DEFAULT '00000';
          DECLARE msg TEXT;
          DECLARE result TEXT;
          declare v_day_dt datetime;
          -- 声明异常处理
          DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
            BEGIN
              -- 获取异常code,异常信息
              GET DIAGNOSTICS CONDITION 1
                code = RETURNED_SQLSTATE, msg = MESSAGE_TEXT;
            END;
       
        SET v_day_dt= STR_TO_DATE(20100229,'%Y%m%d');                
        INSERT INTO sys_calendar (
              day_date,
              year_num,
              month_num,
              day_num,
              day_str,
              day_int
            )
            VALUES
              (v_day_dt,
                2010,
                2,
                29,
                '2020/02/29',
                20200229);  
        select msg,code;
    END$$
DELIMITER ;
执行以上过程,返回结果:

六、小结
1.mysql的存储过程比较垃圾,无论循环控制,异常处理,执行效率,事务控制。虽然已经比过去的版本好了一些些!
2.如果有啥好处,就是可以写一些小函数,当不想写java等高级语言的时候,有个替代选项。
3.希望它赶紧升级,靠向oracle存储过程–不过难度可能有点大。
原创文章,作者:carmelaweatherly,如若转载,请注明出处:https://blog.ytso.com/tech/bigdata/275966.html
