1.情景展示
根据第一个游标的数据产生第二个游标的数据,如何实现遍历?
2.原因分析
3.解决方案
CREATE OR REPLACE PROCEDURE PRC_INDEX_SEARCH(OUT_CURSOR OUT SYS_REFCURSOR) IS /** * 内容:三级指标关联查询 * 日期:2020/04/21 * 作者:MARYDON * 流程:一级指标-->二级指标(合计除外)-->三级指标-->二级指标(只有合计) */ /*查询一级指标(一级指标下如果没有二级指标的话,是不会插入到临时表的)*/ CURSOR CUR_FIRST_INDEX IS SELECT A.ID A_ID, --一级指标ID A.INDEXNAME A_INDEXNAME --一级指标名称 FROM INDEX_A A WHERE A.STATUS = 1 --一级指标处于启用状态 ORDER BY A_ID; /*定义游标变量,该变量的类型为基于游标CUR_FIRST_INDEX的行记录*/ ROW_CUR_FIRST_INDEX CUR_FIRST_INDEX%ROWTYPE; /*一级指标ID*/ V_A_ID INDEX_A.ID%TYPE; /*查询一级指标对应的二级指标 *动态游标数据 */ CURSOR CUR_SECOND_INDEX IS SELECT A.ID A_ID, --一级指标ID A.INDEXNAME A_INDEXNAME, --一级指标名称 A.TOTALWEIGHT A_TOTALWEIGHT, --权重占比 B.ID B_ID, --二级指标ID B.INDEXNAME B_INDEXNAME, ----二级指标名称 B.INDEXSCORE B_INDEXSCORE, --指标分值 B.COUNTER B_COUNTER, --计算方法 B.REMARK B_REMARK, --备注 B.ISTOTAL B_ISTOTAL, --是否合计 B.ISCHILD B_ISCHILD --是否有子指标 FROM INDEX_B B, INDEX_A A WHERE B.STATUS = 1 --二级指标处于启用状态(不用担心一级指标是否禁用问题) AND B.INDEXTYPE = 2 --二级指标 AND B.ISTOTAL = 2 --非合计 AND B.INDEXA_ID = V_A_ID/*必须用变量*/ AND B.INDEXA_ID = A.ID --两表关联 ORDER BY B_ID; /*定义游标变量,该变量的类型为基于游标CUR_SECOND_INDEX的行记录*/ ROW_CUR_SECOND_INDEX CUR_SECOND_INDEX%ROWTYPE; /*定义子指标变量*/ V_ISCHILD INDEX_B.ISCHILD%TYPE; BEGIN -- 1.创建临时表 --2.遍历双重游标(一级指标) /*2.1遍历第一层游标*/ FOR ROW_CUR_FIRST_INDEX IN CUR_FIRST_INDEX LOOP --2.1.1一级指标ID 赋值(第二重游标数据的关键,V_A_ID变化,CUR_SECOND_INDEX数据也会随之改变) V_A_ID := ROW_CUR_FIRST_INDEX.A_ID; /*2.2一级指标对应的二级指标*/ FOR ROW_CUR_SECOND_INDEX IN CUR_SECOND_INDEX LOOP --2.2.1将二重游标行数据插入临时表 INSERT INTO TAB_INDEX_TEMP VALUES (ROW_CUR_SECOND_INDEX.A_ID, ROW_CUR_SECOND_INDEX.A_INDEXNAME, ROW_CUR_SECOND_INDEX.A_TOTALWEIGHT, ROW_CUR_SECOND_INDEX.B_ID, ROW_CUR_SECOND_INDEX.B_INDEXNAME, ROW_CUR_SECOND_INDEX.B_INDEXSCORE, ROW_CUR_SECOND_INDEX.B_COUNTER, ROW_CUR_SECOND_INDEX.B_REMARK, ROW_CUR_SECOND_INDEX.B_ISTOTAL, ROW_CUR_SECOND_INDEX.B_ISCHILD); --2.2.2指标分值 赋值 V_ISCHILD := ROW_CUR_SECOND_INDEX.B_ISCHILD; --2.2.3插入三级指标(1说明有子指标) IF V_ISCHILD = 1 THEN INSERT INTO TAB_INDEX_TEMP SELECT A.ID, A.INDEXNAME, A.TOTALWEIGHT, B.ID B_ID, B.INDEXNAME, B.INDEXSCORE, B.COUNTER, B.REMARK, B.ISTOTAL, B.ISCHILD FROM INDEX_B B, INDEX_A A WHERE B.STATUS = 1 --三级指标启用 AND B.INDEXB_ID = ROW_CUR_SECOND_INDEX.B_ID --三级指标的父级ID AND B.INDEXA_ID = ROW_CUR_SECOND_INDEX.A_ID --一级指标对应的三级指标 AND B.INDEXA_ID = A.ID --两表关联 ORDER BY B_ID; END IF; END LOOP; /*2.3插入二级指标合计行(既可以查询也可以自己手动添加合计行)*/ INSERT INTO TAB_INDEX_TEMP SELECT A.ID, A.INDEXNAME, A.TOTALWEIGHT, B.ID, B.INDEXNAME, B.INDEXSCORE, B.COUNTER, B.REMARK, B.ISTOTAL, B.ISCHILD FROM INDEX_B B, INDEX_A A WHERE B.STATUS = 1 --二级指标处于启用状态(不用担心一级指标是否禁用问题) AND B.INDEXTYPE = 2 --二级指标 AND B.ISTOTAL = 1 --合计项 AND B.INDEXA_ID = V_A_ID AND B.INDEXA_ID = A.ID --两表关联 ORDER BY B.ID; END LOOP; --3.返回最终数据 OPEN OUT_CURSOR FOR --查询临时表数据作为游标结果集 SELECT * FROM TAB_INDEX_TEMP; --不能也不用清空临时表 /*COMMIT;*/ END PRC_INDEX_SEARCH;
第一步:第一个游标CUR_FIRST_INDEX,取每行数据的A_ID当作变量V_A_ID的值,这样当你的V_A_ID发生变化时,第二个游标CUR_SECOND_INDEX的数据也会发生变化;
第二步:遍历双层游标即可。
说明:
1.变量V_A_ID必须得用,如果在定义第二个游标的时候直接用第一个游标的行数据代替,
虽然可以编译成功,但是,将永远查不到数据。
所以,当第二个游标的数据依赖于第一个游标的数据时,必须用变量来代替。
扫描二维码关注公众号,回复:
11158121 查看本文章
2.Oracle的if语句判断值是否相等,不同于Java和js,使用的是一个等号=;
3. 另外,表示elseif的关键词也与那两种语言不同,使用的是ELSIF,少一个E;
4.表示赋值的用,:=;
5.不等于使用,<>。