使用sys_refcursor和临时表返回oracle结果集
sys_refcursor是oracle9i以后系统定义的一个refcursor,主要用在过程中返回结果集。 如果仅仅为了返回值,无需自己在包头中定义游标类型,只需直接使用sys_refcursor即可轻松返回结果。 但如果返回结果需要中间计算,就需要临时表进行存储,最后返回。 1)ON COMMIT DELETE ROWS 会话,指的是客户端连接到服务器的一个上下文环境。它是一个逻辑概念。你比如,创建了一个会话,这个会话记录了客户端的ip,客户端的用户名等信息。以及发布的sql命令的游标等。这些信息都是存储在内存中的。oracle实例赋予一个id(session——id)来逻辑地把这些信息组织在一起。 create or replace PROCEDURE P_RPT_TJ_CREDIT ( V_TYPE VARCHAR2,V_FUN_IDS IN OUT CLOB,V_RESULT OUT SYS_REFCURSOR --系统游标变量,方便返回记录集 ) AS V_SQL VARCHAR2(2048); V_STR VARCHAR2(2048); TYPE CV_FUNS IS REF CURSOR; -- 定义动态游标 CV_FUN CV_FUNS; V_FUN_NAME VARCHAR2(128); V_FUN_KIND VARCHAR2(64); V_ROUTE_ID VARCHAR2(2048); V_FUN_ID VARCHAR2(36); V_INX NUMBER(4); V_BIZ_TYPE VARCHAR2(24); V_YM_DATE CHAR(7); V_NUM NUMBER(10) DEFAULT 0; V_SNUM NUMBER(10) DEFAULT 0; V_PE NUMBER(12,2) DEFAULT 0; CURSOR CV_RESULTS IS SELECT BIZ_TYPE,FUNCTION_ID,YM_DATE,NUM FROM TMP_TJ_CREDIT ORDER BY BIZ_TYPE,YM_DATE; BEGIN DELETE FROM TMP_TJ_CREDIT; -- 清除临时表数据 V_FUN_IDS := '''' || REPLACE(V_FUN_IDS,',''',''') || ''''; V_SQL := 'SELECT ID,FUNCTION_NAME,FUNCTION_KIND,ROUTE_ID FROM SYS_FUNCTION WHERE ID IN (' || V_FUN_IDS || ')'; dbms_output.put_line(V_SQL); OPEN CV_FUN FOR V_SQL; LOOP FETCH CV_FUN INTO V_FUN_ID,V_FUN_NAME,V_FUN_KIND,V_ROUTE_ID; EXIT WHEN CV_FUN%NOTFOUND; -- 循环插入每个给定菜单的数据统计值(每个菜单及其子菜单在每月的数量) IF V_TYPE = 'CREDIT' THEN INSERT INTO TMP_TJ_CREDIT(BIZ_TYPE,NUM) SELECT V_TYPE,V_FUN_ID,SUBSTR(CREATE_DATE,1,7) YM,SUM(TJ_NUM) NUM FROM TJ_CREDIT_DETAIL_INFO WHERE (CHECK_FLAG = '1' OR CHECK_FLAG = '2') AND ( FUNCTION_ID = V_FUN_ID OR FUNCTION_ID IN (SELECT ID FROM SYS_FUNCTION WHERE ROUTE_ID LIKE '%' || V_ROUTE_ID || '%') ) GROUP BY V_TYPE,7) ; ELSE INSERT INTO TMP_TJ_CREDIT(BIZ_TYPE,SUM(TJ_NUM) NUM FROM LOG_DATA_RESULT WHERE (CHECK_FLAG = '1' OR CHECK_FLAG = '2') AND ( FUNCTION_ID = V_FUN_ID OR FUNCTION_ID IN (SELECT ID FROM SYS_FUNCTION WHERE ROUTE_ID LIKE '%' || V_ROUTE_ID || '%') ) GROUP BY V_TYPE,7) ; END IF; END LOOP; --循环计算上月数据及其增长率(同一菜单,且月份是递增(步长1)) V_INX := 0; V_FUN_ID := NULL; FOR CV_RESULT IN CV_RESULTS LOOP IF V_FUN_ID = CV_RESULT.FUNCTION_ID AND V_YM_DATE != CV_RESULT.YM_DATE THEN IF V_YM_DATE IS NOT NULL AND ( TO_NUMBER(SUBSTR(V_YM_DATE,6,2)) + 1 = TO_NUMBER(SUBSTR(CV_RESULT.YM_DATE,2)) ) THEN V_SNUM := V_NUM; IF V_SNUM != 0 THEN V_PE := ROUND((CV_RESULT.NUM -V_SNUM) / V_SNUM *100,2); END IF; END IF; ELSE V_SNUM := 0; V_PE := 0; END IF; UPDATE TMP_TJ_CREDIT SET SNUM = V_SNUM,PE = V_PE WHERE FUNCTION_ID = CV_RESULT.FUNCTION_ID AND YM_DATE = CV_RESULT.YM_DATE; V_BIZ_TYPE := CV_RESULT.BIZ_TYPE; V_FUN_ID := CV_RESULT.FUNCTION_ID; V_YM_DATE := CV_RESULT.YM_DATE; V_NUM := CV_RESULT.NUM; V_SNUM := 0; V_PE := 0; END LOOP; --最后返回结果,包括序号 OPEN V_RESULT FOR SELECT ROWNUM,BIZ_TYPE TYPE,YM_DATE YM,NUM,SNUM,PE FROM( SELECT BIZ_TYPE,PE FROM TMP_TJ_CREDIT ORDER BY BIZ_TYPE,YM_DATE ) A ; END P_RPT_TJ_CREDIT; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |