DATABASE(oracleDB 11g)/PLSQL

[PL/SQL]제어구조문의 기초

SEUNGSAMI 2019. 2. 19. 11:00

제어구조문의 기초



IF 문

기본적인 구문은

1
2
3
4
5
6
7
IF condition THEN
    statements;
[ELSIF condition THEN
    statements;]
[ELSE
    statements;]
END IF;
cs

으로 작성한다.


아마 프로그래밍을 조금이라도 경험한 사람이라면 이 형식은 굉장히 익숙하게 느껴질 것이다.


구문 

설명

condition

T,F,NULL을 반환하는 변수 또는 표현식

THEN

부울표현식을 뒤의 명령문 시퀀스와 연관시키는 절을 시작 

statements

조건이 TRUE인 경우 실행되는 문장 



CASE 식

기본적인 구문은

1
2
3
4
5
6
7
CASE selector
    WHEN expression1 THEN result1    
    WHEN expression2 THEN result2
    ...
    WHEN expressionN THEN resultN
    [ELSE resultN+1]
END;
cs

으로 작성한다.


각각의 expressionN에 따라서 resultN을 반환한다.



CASE 문

위의 CASE 식과 비슷하지만 END CASE;로 종료한다.



LOOP 문

>>기본루프

구문은 다음과 같다.

1
2
3
4
5
LOOP
    statement1;
    ...
    EXIT [WHEN condition];
END LOOP;
cs



다음 예시를 보자

다음의 예시는 명시적 커서를 이용한 블록인다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
DECLARE 
  CURSOR CUR_EMP IS 
   SELECT ENAME, SAL 
   FROM EMP 
   WHERE DEPTNO = 10 ; 
 
  V_ENAME   EMP.ENAME%TYPE ; 
  V_SAL     EMP.SAL%TYPE ;
BEGIN 
  OPEN CUR_EMP ; 
  FETCH CUR_EMP INTO V_ENAME, V_SAL ; 
  DBMS_OUTPUT.PUT_LINE(V_ENAME||' '||V_SAL) ; 
  FETCH CUR_EMP INTO V_ENAME, V_SAL ; 
  DBMS_OUTPUT.PUT_LINE(V_ENAME||' '||V_SAL) ; 
  FETCH CUR_EMP INTO V_ENAME, V_SAL ; 
  DBMS_OUTPUT.PUT_LINE(V_ENAME||' '||V_SAL) ; 
  CLOSE CUR_EMP ; 
END ; 
/
cs

이러한 블록의 경우 FETCH가 많아지면 구문을 작성하기 힘들다는 단점이 있다.

이럴때 LOOP를 사용하면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
DECLARE 
  CURSOR CUR_EMP IS 
   SELECT ENAME, SAL 
   FROM EMP 
   WHERE DEPTNO = 10 ; 
 
  V_ENAME   EMP.ENAME%TYPE ; 
  V_SAL     EMP.SAL%TYPE ;
  V_CNT     NUMBER := 0 ; 
BEGIN 
  OPEN CUR_EMP ; 
  
  LOOP 
    V_CNT  := V_CNT + 1 ; 
    FETCH CUR_EMP INTO V_ENAME, V_SAL ; 
    DBMS_OUTPUT.PUT_LINE(V_ENAME||' '||V_SAL) ; 
    
  EXIT WHEN V_CNT >= 3 ; 
  END LOOP ; 
 
  CLOSE CUR_EMP ; 
END ; 
/
cs



>>FOR 루프

다음과 같은 구문을 사용한다.

1
2
3
4
5
6
FOR counter IN [REVERSE]
        lower_bound..upper_bound LOOP
    statement1;
    statement2;
    ...
END LOOP;
cs


구문

설명

counter

상한 또는 하한에 도달할때까지 1씩 증가 또는 감소하는 정수

REVERSE

반복할때 카운터를 상한에서 하한으로 감소

lower_bound

카운터 값 범위에 대한 하한 지정

upper_bound

카운터 값 범위에 대한 상한 지정


다음 예시를 보자

1
2
3
4
5
6
7
8
9
10
11
BEGIN 
 
 FOR i IN 1..5 LOOP 
  -- i := 2;    --ERROR 
  DBMS_OUTPUT.PUT_LINE('COUNTER: '||i) ; 
 END LOOP ; 
 
-- DBMS_OUTPUT.PUT_LINE('COUNTER: '||i) ;   --ERROR 
 
END ; 
/
cs

여기서 중요한 것은 i라는 변수는 LOOP 안에서는 언제든 참조가 가능하나, LOOP의 바깥에서는 참조가 불가능 하다.

하지만 LOOP 안에서 i에 대해 뭔가 값을 할당하는 것도 불가능하다.


>>WHILE 루프

다음과 같은 구문을 사용한다.

1
2
3
4
5
WHILE condition LOOP
    statement1;
    statement2;
    ...
END LOOP;
cs



>>중첩 루프 및 레이블

LOOP 단어 앞에 레이블 구분자 <<label>>을 두어 기본 루프의 레이블을 지정한다.

다음의 예시를 참고하자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
DECLARE
    v_counter    NUMBER(5) := 0;
    total_done   VARCHAR2(10) := 'YES';
    inner_done   VARCHAR2(10) := 'NO';
BEGIN
    <<outer_loop>> LOOP
        v_counter := v_counter + 1;
        EXIT WHEN v_counter > 10;
        <<inner_loop>> LOOP
            dbms_output.put_line('현재위치 1');
            dbms_output.put_line(total_done);
            dbms_output.put_line(inner_done);
            EXIT outer_loop WHEN total_done = 'YES';
            dbms_output.put_line('현재위치 2');
            dbms_output.put_line(total_done);
            dbms_output.put_line(inner_done);
            EXIT WHEN inner_done = 'YES';
            dbms_output.put_line('현재위치 3');
            dbms_output.put_line(total_done);
            dbms_output.put_line(inner_done);
        END LOOP inner_loop;
    END LOOP outer_loop;
    dbms_output.put_line('빠짐');
END;
/
cs


>>PL/SQL CONTINUE 문

루프 내의 제어를 새 반복으로 전이하거나 루프를 벗어날 수 있다.

다음의 예시를 참고하자.

1
2
3
4
5
6
7
8
9
10
11
12
13
DECLARE
    v_total   NUMBER := 0;
BEGIN
    FOR j IN 1..10 LOOP
        v_total := v_total + j;
        dbms_output.put_line('Total is: ' || v_total);
        CONTINUE WHEN j > 5;
        v_total := v_total + j;
        dbms_output.put_line('Out of Loop Total is:
' || v_total);
    END LOOP;
END;
/
cs



SQL을 배운지 얼마 되지 않아 잘못된 내용이 있을 수 있습니다. 틀린 내용이있다면, 댓글로 달아주세요.