Oracle - 爲子查詢提供動態結果集

曾經遇到過這樣一個需求:要求爲method傳入String,內容如"用戶ID0,用戶ID1,用戶ID2...",而後根據這些ID返回一個結果集做爲數據表供別人查詢。
SELECT * FROM TBL WHERE ID IN ('用戶ID0,用戶ID1,用戶ID2') 不就能夠解決問題嗎?
但實際狀況是,結果集沒法經過一個簡單的SELECT就能夠獲得。 框架


讓我明確一下須要解決的問題: 函數

咱們給FUNCTION傳遞這樣的一個String參數後如何讓它動態RETURN一個結果集供其餘SELECT語句使用。 code


既然咱們要返回一個結果集,那即是要獲得一個TABLE OF XXX類型,XXX能夠是VARCHAR2或者INTEGER或者某個表的%ROWTYPE,但個人狀況稍微複雜一點,我要本身建立一個OBJECT TYPE。對象


因而咱們要寫的FUNCTION的RETURN類型是這樣建立的:開發

CREATE OR REPLACE TYPE TYP_USER_RECORD AS OBJECT (USER_ID CHAR(40),USER_NUM VARCHAR2(200),CREATE_DATE DATE);
CREATE OR REPLACE TYPE TYP_USER_TBL AS TABLE OF TYP_USER_RECORD;


下面是FUNCTION的建立:循環

CREATE OR REPLACE FUNCTION REGROUP_USER_BY_USERIDSTR(USERIDSTR IN VARCHAR2)
  RETURN TYP_USER_TBL
  PIPELINED IS

  --參數聲明開始
  TYPE USER_CURSOR IS REF CURSOR;
  USER_INFO_LIST USER_CURSOR;       --用來得到檢索結果的CURSOR

  TYPE USER_ROW IS RECORD(
    USER_ID CHAR(40),USER_NUM VARCHAR2(200),CREATE_DATE DATE);
  USER_INFO USER_ROW;               --用於提取CURSOR中的記錄的RECORD

  USER_ROW4RESULT TYP_USER_RECORD;  --咱們要返回的數據集的數據行對象
  QUERYSTR          VARCHAR2(2000); --拼接後的SELECT語句
  --參數聲明結束

BEGIN
  --此處根據傳入的ID進行了各類判斷拼接SELECT語句 並給QUERYSTR賦值
  OPEN USER_INFO_LIST FOR QUERYSTR; --打開CURSOR
  --循環從CURSOR得到結果 並將結果變成TYP_USER_RECORD對象 再將對象放到PIPE裏
  LOOP
    FETCH USER_INFO_LIST INTO USER_INFO;
    EXIT WHEN USER_INFO_LIST%NOTFOUND;
    USER_ROW4RESULT := TYP_USER_RECORD(USER_INFO.USER_ID,
                              USER_INFO.USER_NUM,
                              USER_INFO.CREATE_DATE);
    PIPE ROW(USER_ROW4RESULT);
  END LOOP;

  CLOSE USER_INFO_LIST;
  RETURN;
END;


既然RETURN TYPE是TABLE類型的,調用時即可以使用TABLE()函數進行查詢。數據

SELECT * FROM TABLE(REGROUP_USER_BY_USERIDSTR)


另外,本人目前工程中使用的持久化框架是MyBatis,此語句執行無誤。
參數雖然能夠直接傳入SELECT * FROM XX IN ()進行查詢,但也可能須要進行截取變成COLLECION,下面是該功能的FUNCTION: 查詢

CREATE OR REPLACE TYPE TBL_VARCHAR2 AS TABLE OF VARCHAR2(400);

CREATE OR REPLACE FUNCTION STR2TBL( PARAM_STR IN VARCHAR2 ) RETURN TBL_VARCHAR2
  AS
      TMP_RECORD   LONG DEFAULT PARAM_STR || ',';
      ROW_INDEX        NUMBER;
      TMP_TBL    TBL_VARCHAR2 := TBL_VARCHAR2();
  BEGIN
      LOOP
          ROW_INDEX := INSTR( TMP_RECORD, ',' );
          EXIT WHEN (NVL(ROW_INDEX,0) = 0);
          TMP_TBL.EXTEND;
          TMP_TBL( TMP_TBL.COUNT ) := LTRIM(RTRIM(SUBSTR(TMP_RECORD,1,ROW_INDEX-1)));
          TMP_RECORD := SUBSTR( TMP_RECORD, ROW_INDEX+1 );
      END LOOP;
      RETURN TMP_TBL;
  END;



這種方式的意義可能只有讓開發方便了一些,試圖用一句SQL拯救世界必將致使各類問題。
爲何會有這種需求,多是由於數據關係梳理地有些倉促,數據散落在不一樣的數據表。
不管如何這是一個糟糕的場景。co

相關文章
相關標籤/搜索