根據第一個遊標的數據產生第二個遊標的數據,如何實現遍歷?html
三級關聯查詢如何實現?sql
存儲過程如何使用臨時表返回遊標數據?oracle
表結構展現測試
方式一:直接建立fetch
/** * 建立臨時指標表 */ CREATE GLOBAL TEMPORARY TABLE TAB_INDEX_TEMP(A_ID NUMBER,--一級指標ID A_INDEXNAME VARCHAR2(50), --一級指標名稱 A_TOTALWEIGHT NUMBER, --權重佔比 B_ID NUMBER, --二級指標ID B_INDEXNAME VARCHAR2(200), ----二級指標名稱 B_INDEXSCORE NUMBER, --指標分值 B_COUNTER VARCHAR2(200), --計算方法 B_REMARK VARCHAR2(200),--備註 B_ISTOTAL VARCHAR2(2),--是否合計 B_ISCHILD VARCHAR2(2))ON COMMIT DELETE ROWS;/*事務提交時,清空臨時表數據*/
方式二:動態建立spa
DECLARE /* TABLE計數,用於判斷臨時表是否存在*/ V_TAB_COUNT NUMBER(1); /* 用於建立臨時表SQL */ V_TAB_SQL VARCHAR2(1000); BEGIN -- 1.建立臨時表 SELECT COUNT(1) INTO V_TAB_COUNT FROM ALL_TABLES WHERE TABLE_NAME = 'TAB_INDEX_TEMP'; --不存在就建立 IF V_TAB_COUNT = 0 THEN V_TAB_SQL := 'CREATE GLOBAL TEMPORARY TABLE TAB_INDEX_TEMP(A_ID NUMBER, A_INDEXNAME VARCHAR2(50), A_TOTALWEIGHT NUMBER, B_ID NUMBER, B_INDEXNAME VARCHAR2(200), B_INDEXSCORE NUMBER, B_COUNTER VARCHAR2(200), B_REMARK VARCHAR2(200), B_ISTOTAL VARCHAR2(2), B_ISCHILD VARCHAR2(2))'; V_TAB_SQL := V_TAB_SQL || ' ON COMMIT delete ROWS'; /*事務提交時,清空臨時表數據*/ EXECUTE IMMEDIATE V_TAB_SQL; --執行SQL END IF; END;
說明:臨時表類型採用事務類型,至於好處見文章底部連接。htm
也能夠使用會話型臨時表,只不過須要在每次插入前先清空表數據。 blog
三級關聯查詢思路:先查一級指標,根據一級查二級,判斷二級查三級事務
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 = 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的數據也會發生變化;get
第二步:遍歷雙層遊標便可。
說明:
1.變量V_A_ID必須得用,若是在定義第二個遊標的時候直接用第一個遊標的行數據代替,
雖然能夠編譯成功,可是,將永遠查不到數據。
因此,當第二個遊標的數據依賴於第一個遊標的數據時,必須用變量來代替。
2.Oracle的if語句判斷值是否相等,不一樣於Java和js,使用的是一個等號=;
3. 另外,表示elseif的關鍵詞也與那兩種語言不一樣,使用的是ELSIF,少一個E;
4.表示賦值的用,:=;
5.不等於使用,<>;
6.在存儲過程裏,指定變量的數據類型時,能夠動態指定,也就是
一整行數據的數據類型:表名%ROWTYPE,如:ROW_INDEX_A INDEX_A%ROWTYPE;;
某列的數據類型:表名.字段名%TYPE,如:V_A_ID INDEX_A.ID%TYPE;。
在plsql中選中存儲過程,右鍵--》測試--》F8執行--》右下角遊標--》點開查看結果集
層級說明:
----》----》二級
----》----》----》----》三級
----》----》合計
----》----》二級
。。。依此順序循環查詢輸出
哪位大佬如若發現文章存在紕漏之處或須要補充更多內容,歡迎留言!!!