一、环境 数据库:mysql8.0.25 社区版 操作系统:windows 11 ------------------------------------ 二、创建日历表 CREATE TABLE `sys_calendar` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `day_date` datetime DEFAULT NULL ,
数据库: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存储过程--不过难度可能有点大。