조건에 따라 커서조건 변경처리 0 8 9,173

by 마늘장 [PL/SQL] 커서 루핑 [2012.12.10 11:40:41]



동일한 로직처리이나, 입력 파라미터에 따라 커서의 조건을 다르게
가지고 가려합니다.

즉, parameter가 날짜일경우는
cursor A
select
from tbl
where localtime = para1

parameter가 id일 경우는
cursor B
select
from tbl
where id = para2

for 루핑이하 로직처리는 두케이스 동일하고
다만, 조건에 따라 대상 기준 데이터만이 달라지는 경우인데요

IF로 cursor 선언만 분개처리할수도 없고 Dynamic SQL로 담기에는
코딩 분량이 많고, parameter에 따라 (para1 and 조건1 or para2 and 조건2)
where 조건문을 가져가기에는 성능 이슈가 있을거 같습니다.

이런 케이스가 종종 생기는데  어떤식으로 처리하면 될지 현명한 답변
부탁합니다.
 
by 바람이불면 [2012.12.10 12:59:28]
패키지안에 인자를 다르게 받는 동일한 이름의 프로시져를 생성하여 쓰시는게 어떨런지요?

by 마농 [2012.12.10 16:06:52]
Dynamic SQL 사용방법 : http://www.gurubee.net/article/19612

by 마늘장 [2012.12.10 17:45:15]

답변 감사합니다.
고민해 봤습니다만, 프로그램 성격상 Batch이고
두가지의 unique 키 조건으로만 분개처리가 되고 Dynamic SQL의 경우
향후 쿼리에 대한 분석이 용의치 않을것 같습니다.

Static성으로 처리를 하되 Parameter에 따라 둘중 한가지로만
데이타가 추출되도록 하는것이 좋겠다는 판단입니다.

(A 쿼리
 A para1 is not null and localtime 조건)
union all
B 쿼리
B para2 is not null and Id 조건) 

by Oracler [2012.12.11 07:45:24]
오라클 PL/SQL에는 패키지라는 것이 있는데 프로시저와 함수에 대해 OOP의 함수 오버로딩을 지원합니다.
따라서 같은 이름의 프로시저를 만들되 매개변수 개수나 매개변수의 데이터 타입이 다르면 이름이 같은 프로시저, 함수를 정의할 수 있습니다. 

by Oracler [2012.12.11 07:47:29]
 엇, 바람이불면님께서 동일한 답변을 다셨군요. ㅎㅎ

오라클 클럽의 패키지 강의 내용을 참고해 보세요.

http://www.gurubee.net/lecture/1075

by 손님 [2012.12.11 09:58:24]

답변 감사합니다.

제생각에 함수에 대한 오버로딩이란 결국, 각각의 프로시져가 코딩되어 만들어 지는것으로
parameter에 따라 동일한 함수명 또는 프로시져명을 사용할수있다는것은 동의하지만
결국 코딩으로 보자면 개별적으로 작성해야하는것 같습니다.

제가 하고저 하는것은 cursor선언부가 parameter에 따라 값이 다르고
처리하고자 하는 procedure 절은 동일하게 사용하는것입니다.

좀 깊이 생각해 보자면 오라클 패키지는 구조적으로
declare 한 cursor명 하나로만 lopping을 할수있는게 되어있는데
cursor가 dymanic sql로 처리하지 않는이상은 여러가지의 SQL과
static하게 선언되지 못한다것입니다.

Type변수 선언하고 사용하듯이 여러 SQL을 선언하고 cursor와 
mapping한다면 좋겠으나 현실적으로 안되는것 같습니다.

아니면, cursor에 대해서도 오버로딩이 된다면 가능한 얘기일수도 있겠습니다.
 

by 마농 [2012.12.11 11:21:39]

커서를 미리 선언한다는 제한적인 생각만 하고 계시는듯 하네요.
다이나믹 SQL 을 사용하면 미리 커서를 선언하지 않고
조건에 따라 작성된 SQL 문을 커서처럼 사용할 수 있습니다.
위 링크에 사용법은 나와 있구요.
위처럼 간단한 내용이라면 OR 나 UNION ALL 로 풀어도 될것 같구요.
좀더 복잡하고 다양한 경우라면 다이나믹으로 풀어야 할 것 같습니다.


by 손님 [2012.12.11 16:43:13]
CREATE OR REPLACE PROCEDURE XX_TEST_PROC (
            PARA1  VARCHAR2
            ,PARA2  NUMBER )
IS
  CURSOR CUR_A IS
  SELECT *
  FROM SCOTT.EMP
  WHERE JOB = PARA1;

  CURSOR CUR_B IS
  SELECT *
  FROM SCOTT.EMP
  WHERE DEPTNO = PARA2;
  
  REC CUR_A%ROWTYPE;

  PROCEDURE WORK_PROC
  IS
  BEGIN
    DBMS_OUTPUT.PUT(REC.EMPNO || ',');
    DBMS_OUTPUT.PUT(REC.ENAME || ',');
    DBMS_OUTPUT.PUT(REC.JOB || ',');
    DBMS_OUTPUT.PUT_LINE(REC.DEPTNO);
  END WORK_PROC;
BEGIN
  DBMS_OUTPUT.PUT_LINE('*** START');
  IF PARA1 IS NOT NULL
  THEN
    FOR CSR IN CUR_A LOOP
      REC := CSR;
      WORK_PROC;
    END LOOP;
  ELSIF PARA2 IS NOT NULL
  THEN
    FOR CSR IN CUR_B LOOP
      REC := CSR;
      WORK_PROC;
    END LOOP;
  END IF;
  DBMS_OUTPUT.PUT_LINE('*** END');
END XX_TEST_PROC;

-- 실행
DECLARE 
BEGIN
  XX_TEST_PROC('MANAGER',0);
  XX_TEST_PROC('',20);
END ;
-- 결과
*** START
7566,JONES,MANAGER,20
7698,BLAKE,MANAGER,30
7782,CLARK,MANAGER,10
*** END
*** START
7369,SMITH,CLERK,20
7566,JONES,MANAGER,20
7788,SCOTT,ANALYST,20
7876,ADAMS,CLERK,20
7902,FORD,ANALYST,20
*** END
댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입