数据库
首页 > 数据库> > MYSQL8存储过程生成日历表以及异常处理

MYSQL8存储过程生成日历表以及异常处理

作者:互联网

一、环境

数据库: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存储过程--不过难度可能有点大。

 

标签:存储,MYSQL8,DECLARE,日历表,DEFAULT,int,num,msg,day
来源: https://www.cnblogs.com/lzfhope/p/16503880.html