테이블펑션내에 커서사용시 질문드립니다. 0 3 1,424

by zbra [PL/SQL] [2020.03.16 14:17:44]


Function 내부에서 SELECT문을 호출 하여

외부에서 로우단위로 접근이 아닌 테이블단위로 사용하고 싶습니다.

뷰를 사용하니 속도가 너무 오래걸려 아래와 같은 방법을 검색하여 찾았는데

 

하기 페키지의 바디를 컴파일하면 아래와같은 오류가 발생합니다.

[Error] PLS-00306 (24: 23): PLS-00306: 'AOC_TABLE' 호출 시 인수의 갯수나 유형이 잘못되었습니다.

 

어느 부분이 잘 못 되었는지 혹은 다른 방법이 있는지 지적해 주시면 더 찾아보겠습니다.

감사합니다.



--PACKAGE SPEC
CREATE OR REPLACE PACKAGE PKG_TF_TEST
AS
TYPE T_RECORD IS RECORD
(
    COL1 T_TABLE.COL1%TYPE
   ,COL2 T_TABLE.COL2%TYPE
);

TYPE T_TABLE IS TABLE OF T_RECORD;
       
FUNCTION FUNC_SEARCH(P_ORD   IN VARCHAR2
                    ,P_STYLE IN VARCHAR2)
  RETURN T_TABLE;

END PKG_TF_TEST;
/


--PACKAGE BODY
CREATE OR REPLACE PACKAGE BODY PKG_TF_TEST
AS

FUNCTION FUNC_SEARCH(P_ORD   IN VARCHAR2
                    ,P_STYLE IN VARCHAR2)
  RETURN T_TABLE
IS
  C_CURSOR SYS_REFCURSOR;
  C_RECORD T_RECORD;
  V_TABLE  T_TABLE;
  i INTEGER := 0;
BEGIN
  BEGIN
    OPEN C_CURSOR FOR
      SELECT COL1, COL2
        FROM T_TABLE
       WHERE ORD   = P_ORD
         AND STYLE = P_STYLE
         ;
    
    LOOP FETCH C_CURSOR INTO C_RECORD;
      EXIT WHEN C_CURSOR%NOTFOUND;
        V_TABLE.EXTEND;
        V_TABLE(i) := T_TABLE(C_RECORD.COL1
                             ,C_RECORD.COL2);
        i := i + 1;
    END LOOP;
    
    CLOSE C_CURSOR;
  END;             
  RETURN V_TABLE;
END;

END PKG_TF_TEST;
/


--CALL FUNCTION
DECLARE
BEGIN
  SELECT * 
    FROM TABLE(FUNC_SEARCH('A','B'));
END;

by zbra [2020.03.16 14:54:22]

루프 안쪽을 아래와 같이 변경하여 컴파일은 처리했는데 SELECT 를 하게되니

ORA-06504: PL/SQL: Result Set 변수 또는 질의의 리턴 유형이 일치하지 않습니다

요 에러가 나오네요.

    LOOP FETCH C_CURSOR INTO C_RECORD;
      EXIT WHEN C_CURSOR%NOTFOUND;
        V_TABLE.EXTEND;
        V_TABLE(i) := C_RECORD;
        i := i + 1;
    END LOOP;

 


by zbra [2020.03.16 18:41:17]

하기와 같이 구루비의 예제 똑같이 참조해서 했더니 잘 돌아가네요

이 방법이 최선인지는 제능력으로써는 판단이 안섭니다만,

사용하는데는 문제가 없어 일단은 이렇게 사용 해 보아야 겠습니다 :)

 

FUNCTION FUNC_SEARCH(P1 IN VARCHAR2
                    ,P2 IN VARCHAR2)
  RETURN T_TABLE PIPELINED 
AS
  CURSOR C1 IS SELECT COL1, COL2
                 FROM TT
                WHERE COL1 = P1
                  AND COL2 = P2;
  C1_REC   C1%ROWTYPE;
  
  V_RECORD T_RECORD;
  V_TABLE  T_TABLE := T_TABLE();
BEGIN
  OPEN C1;
  LOOP FETCH C1 INTO C1_REC;
    EXIT WHEN C1%NOTFOUND;
    V_RECORD := T_RECORD(C1_REC.COL1
                        ,C1_REC.COL2);
    PIPE ROW(V_RECORD);        
  END LOOP;
  
  CLOSE C1;
  RETURN;
END;

 


by 마농 [2020.03.16 18:53:28]

저는 PL/SQL 로 복잡하게 절차적으로 푸는 것 보다는
SQL 로 한번에 하는 걸 선호합니다.
뷰에 성능이 안나온다면? 뷰를 개선하거나? 뷰를 사용하는 SQL 을 개선하는 방법이 있을 것 같습니다.

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입