본문 바로가기

업무/ORACLE

PL/SQL 에서 Cursor 사용예제

PL/SQL 예제

CURSOR를 선언하여 Row를 한개씩 FETCH하여 무언가 작업을 하고 있군요...


CREATE OR REPLACE PROCEDURE HfaPR_CloseDay
(pDeptH_CD      IN  Varchar2,
pFrom_DT       IN  Varchar2,
pInput_PN      IN  Varchar2)

--- 요건 parameter 선언부 군요..

IS

vRowFlag_TY         HfaT_Day_Cash.RowFlag_TY%TYPE;
vDeptH_CD           HfaT_Day_Cash.DeptH_CD%TYPE;
vSlip_DT            HfaT_Day_Cash.Slip_DT%TYPE;
vAccount_CD         HfaT_Day_Cash.Account_CD%TYPE;
vBank_CD            HfaT_Day_Cash.Bank_CD%TYPE;
vBank_DS            HfaT_Day_Cash.Bank_DS%TYPE;
vDSum_0_CT          HfaT_Day_Cash.DSum_0_CT%TYPE;
vDSum_Tot_AM        HfaT_Day_Cash.DSum_Tot_AM%TYPE;
vDTran_0_AM         HfaT_Day_Cash.DTran_0_AM%TYPE;
vDTran_BDayLef_AM   HfaT_Day_Cash.DTran_BDayLef_AM%TYPE;
vDCash_CDay_CT      HfaT_Day_Cash.DCash_CDay_CT%TYPE;
vDCash_CDay_AM      HfaT_Day_Cash.DCash_CDay_AM%TYPE;
vCSum_0_CT          HfaT_Day_Cash.CSum_0_CT%TYPE;
vCSum_Tot_AM        HfaT_Day_Cash.CSum_Tot_AM%TYPE;
vCTran_0_AM         HfaT_Day_Cash.CTran_0_AM %TYPE;
vCTran_BDayLef_AM   HfaT_Day_Cash.CTran_BDayLef_AM%TYPE;
vCCash_CDay_CT      HfaT_Day_Cash.CCash_CDay_CT%TYPE;
vCCash_CDay_AM      HfaT_Day_Cash.CCash_CDay_AM%TYPE;
vInput_PN           HfaT_Day_Cash.Input_PN%TYPE;

vDT_From            HfaT_Day_Cash.Slip_DT%TYPE;
vCount              Number(6);

-------요기까진 변수 선언부구요...

CURSOR Curr_Cash_Sum IS
Select Slip_DT, DCash_CDay_AM, CCash_CDay_AM
 From Hfat_Day_Cash
Where RowFlag_TY = 'C' and
      DeptH_CD = vDeptH_CD and
      Slip_DT = vDT_From
Order By Slip_DT;

-------이부분이 커서 선언부입니다...
HfaT_Day_Cash라는 테이블에서 Where 조건이 걸린 몇개의 컬럼들을
Slip_DT order로 Select를 했군요...


BEGIN

vDeptH_CD     := Rtrim(pDeptH_CD);
vDT_From      := Rtrim(pFrom_DT);

------요긴 파라메타로 받은 값을 특정변수에 Move..

OPEN Curr_Cash_Sum;

------자.. 이제 커서를 Open 합니다...
위에 선언한 커서이름으로 Open 해야겠지요?

LOOP

-----이제 Loop를 돌리는 군요..
왜 Loop를 돌릴까요?
커서를 선언하면 해당 SQL문장을 실행하여 Data 를 가져옵니다...
data를 가져온 상태에서 첫번째 Row부터 한개씩 작업을 하기 위해서 입니다.
그럼 또 계속 볼까요..

    FETCH Curr_Cash_Sum INTO vSlip_DT, vDCash_CDay_AM, vCCash_CDay_AM;
    EXIT WHEN Curr_Cash_Sum%NOTFOUND;

-----Fetch를 하는데.. 특정변수에 값을 Move 시키죠?
data가 마지막에 이르렀을때,, Exit를 하라는군요..
하긴 죽을때까지 무한 루프를 돌리면 안되겠지요?

        Update HfaT_Day_Cash
       Set DTran_BDayLef_AM = vDSum_Tot_AM - vCSum_Tot_AM,
           CTran_BDayLef_AM = 0,
           DSum_Tot_AM = vDCash_CDay_AM + (vDSum_Tot_AM - vCSum_Tot_AM),
           CSum_Tot_AM = vCCash_CDay_AM
     Where RowFlag_TY = 'C' and
           DeptH_CD = vDeptH_CD and
           Slip_DT = vSlip_DT;

        vDSum_Tot_AM := vDCash_CDay_AM + (vDSum_Tot_AM - vCSum_Tot_AM);
        vCSum_Tot_AM := vCCash_CDay_AM;

-----가져온 Data를 가공하여 해당 테이블 특정 컬럼에 Update를 하는군요..
Total값은 누계를 하면서 다음 Row에 반영하는 군요..

END LOOP;

-----Loop를 막아줍니다..

Commit;

-----해당 작업을 마치고 Commit를 시킵니다..

END;
/

사실 insert, Update 조건이 복잡한경우,,
개발자는 고민을 하게됩니다..
복잡한 Sql문장을 구사하여 완빵에 날려버릴건지.. 아님..
커서를 사용하여,, 길지만, 편안하게 코딩할건지...

제생각은 어설프게 작성한 한 문장보다는 길게 풀어쓴 코딩이
유지보수하기두 편하구,, 작성하기두 편하다고 생각해용..

물론 잘 작성된 한개의 문장은 몇천라인 작성한 코딩보다 값어치가 있지만요...