1、前言
作为一个工作了很多年的程序员来说,没有在实际工作中真正使用过存储过程,其实对存储过程本身有过了解和学习,在日常的学习中,也会看过一些存储过程的相关介绍,不过“纸上得来终是浅”,正好这次做统计分析的业务功能时,适合使用存储过程的机会,就搞起来了,顺便记录一些遇见的一些问题,方便后续查看和学习。
业务场景
根据一个时间区间(startTime,endTime)和机构编码(orgCode)从不同维度查询一类数据的多个指标项(num1,num2,num3,num4等),每个数据项都对应一个SQL查询语句。
2、使用Navicat创建存储过程
下面是完整的创建存储过程的SQL语句(直接在Navicat执行会出现报错)。
CREATE PROCEDURE queryNumByCounty(
IN startTime Date,
IN endTime Date,
IN orgCode VARCHAR(20),
OUT num1 INT, -- 指标1
OUT num2 INT, -- 指标2
OUT num3 INT, -- 指标3
OUT num4 INT) -- 指标4
BEGIN
-- 指标1
SELECT
count(T.id) INTO num2
FROM
t_test T
WHERE
T.is_chg != 2
AND STATUS = '0'
AND T.county_id = orgCode
AND T.create_time BETWEEN startTime AND endTime
AND T.phase_type = 6
-- 指标2
SELECT
count(T.id) INTO num2
FROM
t_test T
WHERE
T.is_chg != 2
AND STATUS = '0'
AND T.county_id = orgCode
AND T.create_time BETWEEN startTime AND endTime
AND T.phase_type = 6 AND T.count > 0
-- 指标3
SELECT
count(T.id) INTO num3
FROM
t_test T
WHERE
T.is_chg != 2
AND STATUS = '0'
AND T.county_id = orgCode
AND T.create_time BETWEEN startTime AND endTime
AND T.phase_type = 6 AND T.postpone_status = 2
-- 指标4
SELECT
count(T.id) INTO num4
FROM
t_test T
WHERE
T.is_chg != 2
AND STATUS = '0'
AND T.county_id = orgCode
AND T.create_time BETWEEN startTime AND endTime
AND T.phase_type = 6 AND T.third_count > 0
END;
上述存储过程的SQL语句直接在Navicat执行会出现报错“Can’t create a PROCEDURE from within another stored routine”。原因是因为:在Navicat中创建存储过程,不需要声明事件类型,事件名称、参数等,直接begin~end就可以了,即不需要上述SQL中的前8行代码。
在Navicat上测试和验证存储过程,点击“运行”,需要输入参数,包括入参和出参,其中入参直接输入参数值即可,出参输入“@参数名”,各参数间“,”分隔即可,效果如下:
3、Mybatis中的调用
下面是在Mybatis中调用存储过程的代码:
XML配置文件
注意一定要添加statementType="CALLABLE"属性。
<select id="queryNumByCounty" resultType="map" statementType="CALLABLE">
{call queryCaseNumByCounty(
#{startTime,mode=IN},
#{endTime,mode=IN},
#{orgCode,mode=IN},
#{num1,mode=OUT,jdbcType=INTEGER},
#{num2,mode=OUT,jdbcType=INTEGER},
#{num3,mode=OUT,jdbcType=INTEGER},
#{num4,mode=OUT,jdbcType=INTEGER}
)}
</select>
Java代码
这里的返回值,没有作用,我们需要的返回值都在参数param中。这里省略了Service、Controller层的代码,和平常的编程没有区别。
/**
* 指标统计 存储过程实现,
* @param param
* @return
*/
public Map<String,Object> queryNumByCounty(Map<String,Object> param);