一、环境

数据库: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'。

四、执行存储过程

4.1生成日表

CALL sp_createcalendar(2010,2030);

查询看看结果:

SELECT * FROM sys_calendar;
SELECT COUNT(*),year_num FROM sys_calendar GROUP BY year_num;

4.2生成年表月表

CREATE TABLE sys_cal_year(
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
year_num INT UNSIGNED UNIQUE NOT NULL,
year_str VARCHAR(4) NOT NULL,
PRIMARY KEY(id)
) COMMENT '日历年份表';
INSERT INTO sys_cal_year(year_num,year_str)
SELECT year_num,year_num AS year_str FROM (
SELECT DISTINCT year_num FROM sys_calendar
) vy; --
CREATE TABLE sys_cal_yearmonth(
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
yearmonth_int INT UNSIGNED UNIQUE NOT NULL,
yearmonth_str VARCHAR(6) NOT NULL,
PRIMARY KEY(id)
) COMMENT '日历年月表'; INSERT INTO sys_cal_yearmonth(
yearmonth_int,
yearmonth_str)
SELECT yearmonth_num,yearmonth_num FROM (
SELECT DISTINCT year_num*100+month_num AS yearmonth_num FROM sys_calendar
)vym;

五、获取异常状态信息(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存储过程生成日历表以及异常处理的更多相关文章

  1. SQL Server 2008空间数据应用系列十:使用存储过程生成GeoRSS聚合空间信息

    原文:SQL Server 2008空间数据应用系列十:使用存储过程生成GeoRSS聚合空间信息 友情提示,您阅读本篇博文的先决条件如下: 1.本文示例基于Microsoft SQL Server 2 ...

  2. Sqlserver存储过程生成日期维度

    话不多说,之前已经有一篇日志是利用oracle的存储过程生成日期维度表,接下来我们就用sqlserver来实现这个操作,如下面的步骤所示 1:创建日期维度表(Dim_time) USE [DW] GO ...

  3. SQL Server 存储过程生成流水号

    SQL Server利用存储过程生成流水号 USE BiddingConfig SET QUOTED_IDENTIFIER ON SET ANSI_NULLS ON GO -- =========== ...

  4. 用SQL存储过程生成唯一单据号

    用SQL存储过程生成唯一单据号     在一些系统中,经理要生成单据号,为了不使多台客户端生成的单据号重复,一般要在服务端生成这种流水号,本文是在数据库中生成流水号,并且可以生成多种类型的单据号(比如 ...

  5. MySql生成日历表

    mysql使用存储过程,创建日历表: 准备日历表: CREATE TABLE `m_dim_day` ( `ID` ) NOT NULL AUTO_INCREMENT, `DAY_ID` ) DEFA ...

  6. SQL Server 存储过程生成insert语句

    你肯定有过这样的烦恼,同样的表,不同的数据库,加入你不能执行select  insert 那么你肯定需要一条这样的存储过程,之需要传入表明,就会给你生成数据的插入语句. 当然数据表数量太大,你将最好用 ...

  7. Mysql存储过程(四)——异常处理

    http://blog.csdn.net/crazylaa/article/details/5368421 有时候,不希望存储过程抛出错误中止执行,而是希望返回一个错误码. MySQL 支持异常处理, ...

  8. SQL存储过程生成顺序编码

    一.第一种方式 USE [WJKC]GO/****** Object:  StoredProcedure [dbo].[Address_GetCode1]    Script Date: 2016/3 ...

  9. SQL SERVER存储过程生成字母+数字的编码

    公司内设备管理系统中设备建账功能,功能目的是对新进设备进行记录并入库.其中设备编号一项定义为自己修改(查看之前的设备号,取一个不重复的值来填写),感觉特别麻烦!用存储过程自动生成编码岂不是更效率. 需 ...

  10. Oracle存储过程生成日期维度

    在数据仓库的创建过程中,往往需要创建日期维度来为以后的数据分析来服务. 方面从多个日期角度: 如:年-月-日,年-季度-月-日,年-周-日 创建表的脚本如下(存储过程的创建过程中有一步操作是向time ...

随机推荐

  1. [FAQ] Python list 的值是带有小括号的是什么意思 ?

    python 中的 list 即列表,是用中括号 [ ] 表示的数组列表: dict 即字典,是用花括号 { } 表示的 json 对象: tuple 即元祖,是用小括号表示的序列: 见到它们之间的组 ...

  2. 【Android】Binder的Oneway拦截

    在某些虚拟化,免安装,打点,环境检测,拦截器等场景,针对Android系统服务接口的拦截是常用的技术方案.通常只是针对正向的接口调用,如果涉及被动的服务回调拦截,则实现起来就有些许麻烦. 说明 由于我 ...

  3. [Oracle故障处理]ORA-30012: undo tablespace 'UNDOTBS1' does not exist

    场景:用RMAN在异机上恢复数据. 错误信息如下: ORA-01092: ORACLE instance terminated. Disconnection forced ORA-30012: und ...

  4. MySQL 数据库重置密码

    1.Linux 中 MySQL 数据库重置密码 停止服务:systemctl stop mysql 打开 my.cnf(没有则创建一个):vim /etc/my.cnf 在 [mysqld] 下添加: ...

  5. 更新Homebrew时候遇到的问题

    问题描述: 更新Homebrew时候遇到无法访问github的问题,判定原因为DNS污Ran. fatal: unable to access 'https://github.com/Homebrew ...

  6. vue 安装教程(如何在node环境下搭建vue项目)

    如果要配置node.js环境请查看(node.js环境在Window和Mac中配置,以及安装cnpm和配置Less环境)在终端输入命令 cnpm -v出现版本号 1.安装vue    window : ...

  7. java的jdbc插入的时候,遇到null情况报错问题

    分析原因: 在执行SQL时MyBatis会自动通过对象中的属性给SQL中参数赋值,它会自动将Java类型转换成数据库的类型.而一旦传入的是null它就无法准确判断这个类型应该是什么,就有可能将类型转换 ...

  8. 如何使用 JS 判断用户是否处于活跃状态

    有时候,我们需要在网页判断用户是否处与非活跃状态,如果用户长时间没有在页面上进行任何操作,我们则判定该用户是非活跃的. 在 javascript 中我们可以通过监听某些鼠标或键盘相关的事件来判定用户是 ...

  9. 配置Ingress支持HTTPS访问(二):使用cert-manager申请证书

    目录 一.系统环境 二.前言 三.Let's Encrypt和cert-manager简介 四.部署cert-manager 4.1 安装cert-manager 4.2 创建clusterissue ...

  10. 用【Makefile】或【Cmake】编译【C/Fortran】程序文件

    一.vimrc文件设置 set tabstop=4 "tab空格4 set expandtab "将tab扩展成空格 set softtabstop=4 "表示在编辑模式 ...