오라클 이중 FOR 문 - olakeul ijung FOR mun

[반복문]

Show

- Basic Loop : LOOP END LOOP 키워드 사이의 LOOP 블록을 계속 수행한다. 도중에 EXIST WHEN 절이 만족되면 LOOP를 탈출한다.

LOOP
  statement1;
  . . .
  EXIT [WHEN condition];
END LOOP;

- While Loop : 일반적인 WHILE Loop와 유사하다.

WHILE condition LOOP
    statement1;
    statement2;
    . . .
END LOOP;

- For Loop : lower_bound..upper_bound이므로, lower_bound upper_bound 보다 큰 경우 FOR 루프를 진입하지 않는다. 따라서 REVERSE 키워드를 넣으면 반대로 counter가 내려간다.

루프 안에 카운터만 참조해야 하며, 루프 밖에는 카운터가 정의되어 있지 않다. 또한 카운터를 할당 대상으로 참조하는 것을 피해야하며, 루프의 상한이나 하한을 NULL일 수 없다.

FOR counter IN [REVERSE]
       lower_bound..upper_bound LOOP
    statement1;
    statement2;
    . . .
END LOOP;

- 중첩 루프 및 레이블
1) 다중 레벨로 루프를 중첩시킬 수 있다.

2) 블록과 루프의 구분에 레이블을 사용한다.

3) 레이블을 참조하는 EXIT 문을 사용하여 외부 루프를 종료한다.

...
BEGIN
    <<Outer_loop>>
    LOOP
        v_counter := v_counter+1;
    EXIT WHEN v_counter>10;
        <<Inner_loop>>
        LOOP
            ...
            EXIT Outer_loop WHEN total_done = 'YES';
            -- Leave both loops
            EXIT WHEN inner_done = 'YES';
            -- Leave inner loop only
            ...
        END LOOP Inner_loop;
        ...
    END LOOP Outer_loop;
END;
/

LOOP문

PL/SQL의 기본적인 반복문. EXIT를 누락시키면 무한루프에 빠지니 주의해야한다.

LOOP

처리문;

EXIT  [WHEN 조건]

END LOOP;

cs

예제

DECLARE

VN_BASE_NUM   NUMBER := 3;

VN_CNT        NUMBER := 1;

BEGIN

LOOP

DBMS_OUTPUT.PUT_LINE(VN_BASE_NUM || '*' || VN_CNT || '=' || VN_BASE_NUM * VN_CNT);

VN_CNT := VN_CNT + 1;

EXIT  WHEN VN_CNT > 9;

END LOOP;

END;

cs

WHILE문

LOOP와 비슷하나 WHILE 뒤에 조건을 붙여, 해당 조건을 만족할 때 반복한다.

WHILE 조건

LOOP

처리문;

END LOOP;

cs

예제

DECLARE

VN_BASE_NUM   NUMBER := 3;

VN_CNT        NUMBER := 1;

BEGIN

WHILE VN_CNT < 9

LOOP

DBMS_OUTPUT.PUT_LINE(VN_BASE_NUM || '*' || VN_CNT || '=' || VN_BASE_NUM * VN_CNT);

VN_CNT := VN_CNT + 1;

END LOOP;

END;

cs

DECLARE

VN_BASE_NUM   NUMBER := 3;

VN_CNT        NUMBER := 1;

BEGIN

WHILE VN_CNT < 9

LOOP

DBMS_OUTPUT.PUT_LINE(VN_BASE_NUM || '*' || VN_CNT || '=' || VN_BASE_NUM * VN_CNT);

EXIT  WHEN VN_CNT = 5;

VN_CNT := VN_CNT + 1;

END LOOP;

END;

cs

FOR문

FOR 인덱스 IN [REVERSE] 초기값..최종값

LOOP

처리문;

END LOOP;

cs

인덱스는 루프 안에서 참조할 수 있으나 변경할 수 없다.

예제

DECLARE

VN_BASE_NUM   NUMBER := 3;

BEGIN

FOR IDX IN 1..9

LOOP

DBMS_OUTPUT.PUT_LINE(VN_BASE_NUM || '*' || IDX || '=' || VN_BASE_NUM * IDX);

END LOOP;

END;

cs

DECLARE

VN_BASE_NUM   NUMBER := 3;

BEGIN

FOR IDX IN REVERSE 1..9

LOOP

DBMS_OUTPUT.PUT_LINE(VN_BASE_NUM || '*' || IDX || '=' || VN_BASE_NUM * IDX);

END LOOP;

END;

cs

CONTINUE문

반복문 내에서 특정 조건에 부합할 때 처리 로직을 건너뛰고 상단의 루프 조건으로 건너가 루프를 계속 수행할 때 사용한다.

EXIT는 루프를 완전히 빠져나오지만, CONTINUE는 제어 범위가 조건절로 넘어간다.

예제

DECLARE

VN_BASE_NUM   NUMBER := 3;

BEGIN

FOR IDX IN REVERSE 1..9

LOOP

CONTINUE  WHEN IDX=5;

DBMS_OUTPUT.PUT_LINE(VN_BASE_NUM || '*' || IDX || '=' || VN_BASE_NUM * IDX);

END LOOP;

END;

cs

GOTO문

GOTO문을 만나면 GOTO문이 지정하는 라벨로 제어가 넘어간다.

현장에서는 GOTO문을 잘 사용하지 않는다. 왜냐하면 일반적으로 특정 로직에 맞게 PL/SQL 코드를

순차적으로 작성하는데, 중간중간에 GOTO문을 사용해 제어를 다른 부분으로 넘기면 로직의 일관성을 훼손하기 때문이다.

소스코드가 길어지면 이 문제가 더 심각해져 소스코드의 가독성이 극도로 나빠진다.

예제

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

DECLARE 

VN_BASE_NUM   NUMBER := 3;

BEGIN

<<THIRD>>

FOR IDX IN 1..9

LOOP

DBMS_OUTPUT.PUT_LINE(VN_BASE_NUM || '*' || IDX || '=' || VN_BASE_NUM * IDX);

IF IDX = 3 THEN

GOTO FOURTH;

END IF;

END LOOP;

<<FOURTH>>

VN_BASE_NUM := 4;

FOR IDX IN 1..9

LOOP

DBMS_OUTPUT.PUT_LINE(VN_BASE_NUM || '*' || IDX || '=' || VN_BASE_NUM * IDX);

END LOOP;

END;

cs

NULL문

NULL문은 아무것도 처리하지 않는 문장이다.

보통 IF문이나 CASE문을 작성할때 주로 사용하며, ELSE절을 수행할 때 아무것도 처리하지 않고 싶을때 사용한다.

구조

IF  VN_VARIABLE = 'A' THEN

처리로직1;

ELSIF VN_VARIABLE = 'B' THEN

처리로직2;

...

ELSE

NULL;

END IF;

cs

CASE  WHEN  VN_VARIABLE = 'A' THEN

처리로직1;

WHEN  VN_VARIABLE = 'B' THEN

처리로직2;

...

ELSE  NULL;

END CASE;

cs