본문 바로가기

DB

Oracle(PL/SQL) 제어문

반응형

절차적 언어인 PL/SQL 은 다른 프로그래밍 언어에서 제공하는 다양한 처리문들을 포함하는데 이를 통칭해 PL/SQL 제어문이라고 한다.

 

IF 조건 THEN
조건 처리;
IF

IF조건 THEN
조건 처리1;
ELSE 
조건 처리2;
END IF

IF조건1 THEN
조건처리1;
ELSEIF 조건2 THEN
조건 처리2;

ELSE
	조건처리N;
    END IF;
    
    

IF 다음에 오는 조건값이 ,측 TRUE 이면 해당 조건 처리 문장이 실행된다. 조건 다음에는 THEN을 문장 맨 마지막에는 END IF를 명기해야한다 조건이 1개 이상이면 ELSE IF 가 아닌 ELSIF를 사용한다.

 

DECLARE
            VN_NUM1 NUMBER := 1;
            VN_NUM2 NUMBER := 2;          
            BEGIN 
              IF VN_NUM1 >= VN_NUM2 THEN
                DBMS_OUTPUT.put_LINE(VN_NUM1 ||'이큰수');              
                ELSE
                 DBMS_OUTPUT.PUT_LINE(VN_NUM2 || '이큰수');                
                 END IF;               
                 END;

VN_NUM2 가VN_NUM1 보다 크므로 ELSE 부분으로 제어가 넘어가 실행된 것을 확인할수있다.

 

 

 DECLARE
          VN_SALARY NUMBER :=0;
          VN_DEPARTMENT_ID NUMBER :=0;
          
           BEGIN
            VN_DEPARTMENT_ID := ROUND(DBMS_RANDOM.VALUE(10,120) -1);
            
              SELECT SALARY
              INTO VN_SALARY
              FROM EMPLOYEES 
              WHERE DEPARTMENT_ID = VN_DEPARTMENT_ID
              AND ROWNUM =1;
           
            DBMS_OUTPUT.PUT_LINE(VN_SALARY);
            EXCEPTION
                WHEN NO_DATA_FOUND THEN
            
            IF VN_SALARY BETWEEN 1 AND 300.000 THEN
              DBMS_OUTPUT.PUT_LINE('낮음');
            ELSIF VN_SALARY BETWEEN 3001 AND 600.000 THEN
              DBMS_OUTPUT.put_LINE('중간');
            ELSIF VN_SALARY BETWEEN 6001 AND 1000.000 THEN
              DBMS_OUTPUT.PUT_LINE('높음');
              ELSE 
                DBMS_OUTPUT.PUT_LINE('최상위');
                END IF;
                
             END;

앞의 익명 블록은 7장에서 샘플 데이터를 생성할 때 사용했던 DBMS_RANDOM 패키지를 사용해 10부터 120까지 숫자를 생성한 후 10의 자리(-1)에서 ROUND(올림) 처리를 해서 실행할 때마다 무작위로 10,20,30 ..120 까지 수를  VN_DEPARTMENT_ID 변수에 할당한다. 이로 인해 PL/SQL 블록의 실행 결과는 실행할 때마다 달라질 것이다.

그리고 나서 이 변수값에 해당하는 부서번호를 가진 사원을 무작위로 1명 선택해 급여를 가져와 VN_SALARY 변수에 넣어 IF문을 사용해 범위에 맞게 출력하는 로직이다. 급여가 3000이하 이면 낮음 3001에서 6000까지는 '중간'. 6001에서 10000까지는 '높음' 그이상은 '최상위' 라는 텍스트를 출력하고 있다. 이처럼 여러 조건을 검토해 로직을 처리할 때는 IF ~ELSIF ~ELSE IF 구문을 사용한다

 

 

 DECLARE
          VN_SALARY NUMBER :=0;
          VN_DEPARTMENT_ID NUMBER :=0;
          VN_COMMISSION NUMBER := 0;
          
           BEGIN
            VN_DEPARTMENT_ID := ROUND(DBMS_RANDOM.VALUE(10,120) -1);
            
              SELECT SALARY
              INTO VN_SALARY
              FROM EMPLOYEES 
              WHERE DEPARTMENT_ID = VN_DEPARTMENT_ID
              AND ROWNUM =1;
           
            DBMS_OUTPUT.PUT_LINE(VN_SALARY);
            EXCEPTION
                WHEN NO_DATA_FOUND THEN
            
                IF VN_COMMISSION > 0 THEN
                   IF VN_COMMISSION > 1.5 THEN
                     DBMS_OUTPUT.PUT_LINE(VN_SALARY * VN_COMMISSION);
                     
                     END IF;
                     ELSE 
                       DBMS_OUTPUT.PUTLINE(VN_SALARY);
                       END IF;
             END;

커미션이 0보다 클경우 다시 조건을 걸어 커미션이 0.15 보다 크면 '급여 * 커미션' 결과를 출력하고 커미션이 0 보다 작으면 급여만 출력하고 있다.

 

CASE

 

CASE 표현식 
	WHEN 결과1 THEN
    	처리문1;
    WHEN 결과2 THEN
    	처리문2;
    WEN 결과3 THEN
    	처리문3;
        
    ELSE 
     	기타 처리문;
    
    END CASE;
    
    
    CASE WHEN 표현식1 THEN
    		 처리문1;
             
             WHEN 표현식2 THEN
             		처리문2;
                    
                    ELSE
                    	기타 처리문;
                        
                        END CASE;
                     

 두가지 유형으로 CASE문을 사용할 수있는데, 첫번째 CASE 다음에 바로 표현식을 두고 이 표현식 결과값에 따라 WHEN THEN 에서 처리하는 유형이다. 두 번째 유형은 표현식 자체를 각각의 WHEN 다음에 두고 THEN 이하에서 처리하는데 보통 후자를 많이 사용한다. 그 이유는 WHEN 이하에서 다양한 표현식을 사용해 조건을 검색할수 있기 때문이다. 

 

DECLARE
       VN_SALARY NUMBER := 0;
       VN_DEPARTMENT_ID NUMBER := 0;
 BEGIN
   VN_DEPARTMENT_ID := ROUND(DBMS_RANDOM.VALUE(10,120),-1);
   
   SELECT SALARY
   INTO VN_SALARY
   FROM EMPLOYEES
   WHERE DEPARTMENT_ID = VN_DEPARTMENT_ID
   AND ROWNUM = 1;
        DBMS_OUTPUT.PUT_LINE(VN_SALARY);
   CASE WHEN VN_SALARY BETWEEN 0 AND 300.000THEN
        DBMS_OUTPUT.PUT_LINE('낮음');
        WHEN VN_SALARY BETWEEN 3001 AND 600.000 THEN
        DBMS_OUTPUT.PUT_LINE('중간');
        WHEN VN_SALARY BETWEEN 6001 AND 100.000 THEN
        DBMS_OUTPUT.PUT_LINE('높은');
        ELSE 
          DBMS_OUTPUT.PUT_LINE('최상위');
          END CASE;
       END;

 

LOOP

 

LOOP문은 루프를 돌며 반복해서 로직을 처리하는 반복문이다.

 

LOOP
	처리문;
    EXIT [WHEN 조건]
END LOOP;

LOOP문은 LOOP~ END LOOP 형태로 사용한다. 반복문은 특정 조건을 만족할 때만 루프를 돌며 로직을 처리헤야 하는데. LOOP 문은 특정 조건이란 것이없다. 그 대신 "이런 경우에 루프를 빠져 나가라' 라는 EXIT 를 사용해 루프를 종료한다. 따라서 EXIT 를 누락하면 무한루프에 빠지게 되니 사용할 때 주의해야 한다. 일반적으로 LOOP 문에서는 IF문을 사용해 루프를 빠져나가는 조건을 걸기도 하지만 EXIT WHEN 조건을 사용해 WHEN 절에서 명시한 조건에 맞을때 빠져 나가라고 명시할 수 있다. 

 

       
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;

루프를 돌면서 VN_CNT 값이 1씩 증가한다 VN_CNT 가 9보다 크면 루프 종료

 

WHILE 문

 

WHILE 조건
LOOP
처리문;
END LOOP;

WHILE문은 LOOP 문과 비슷하지만 WHILE 다음에 조건을 붙여 해당 조건에 만족할 때만 루프를 돌면서 로직을 처리한다.

 

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;

LOOP문과 달리 VN_CNT값이 9보다 작거나 같은 경우라는 조건을 주었다는 점이다.

LOOP문에서는 루프를 빠져 나가는 조건을 주었지만 WHILE 문에서는 루프를 수행하는 조건을 준것이다.

WHILE문에서도 루프를 돌다가 특정 조건에 부합하면 EXIT를 써서 루프를 빠져나올 수 있다.

 

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;
             EXIT WHEN VN_CNT = 5;
             END LOOP;
             END;

 

 

FOR

 

FOR 인덱스 IN [REVERSE] 초기값 .. 최종값
  LOOP
    처리문;
    END LOOP;

인덱스 초깃값에서 시작해 최종값까지 루프를 돌며 1씩 증가되는데 인덱스는 참조는 가능하지만

변경할 수는 없고 참조도 오직 루프 안에서만 가능하다. 그리고 REVERSE를 명시하면 순서가 거꾸로 된다.

즉 최종값부터 시작해 최솟값에 이르기까지 감소하면서 루프를 돈다. 구구단 3단을 출력하는 익명 FOR문을 만들어보자

 

DECLARE
       VN_BASE_NUM NUMBER := 3;
      
       
       BEGIN
          FOR I IN 1..9
            LOOP
                DBMS_OUTPUT.PUT_LINE(VN_BASE_NUM ||'*'||I||'='|| VN_BASE_NUM * I);
                END LOOP;
            END;

루프에서 사용하는 인덱스는 선언부에서 선언하지 않고 사용했음을 유념하자. 

 

DECLARE
       VN_BASE_NUM NUMBER := 3;
      
       
       BEGIN
          FOR I IN REVERSE 1..9
            LOOP
                DBMS_OUTPUT.PUT_LINE(VN_BASE_NUM ||'*'||I||'='|| VN_BASE_NUM * I);
                END LOOP;
            END;

REVERS 를 사용해 순서를 바꾸면 3 * 9 부터 결과값을 확인할수 있다.

 

CONTINUE문

CONTINUE문은 FOR나 WHILE같은 반복문은 아니지만, 반복문 내에서 특정 조건에 부합할때 처리 로직을 건너뛰고

상단의 루프 조건으로 건너가 루프를 계속 수행할 때 사용한다. EXIT는 루프를 완전히 빠져 나오는데 반해, CONTINUE는 제어 범위가 조건절로 넘어간다 참고로 CONTINUE문은 오라클 11G 버전부터 지원하고 있다. 구구단 3단에서 5를 제외하는 문장을 작성해 보자.

 

       
DECLARE
       VN_BASE_NUM NUMBER := 3;
      
       
       BEGIN
          FOR I IN REVERSE 1..9
            LOOP
                CONTINUE WHEN I = 5;
                DBMS_OUTPUT.PUT_LINE(VN_BASE_NUM ||'*'||I||'='|| VN_BASE_NUM * I);
                END LOOP;
            END;

 

CONTINUE문을 사용해 인덱스 I값이 5가 됐을 때는 하단의 로직을 수행하지 않고 다시 FOR조건절로 제어가 옮겨져 처리됐음을 알 수 있다.

 

 

GOTO

PL/SQL 코드 상에서 GOTO문을 만나면 GOTO 문이 지정하는 라벨로 제어가 넘어간다.

 

       
DECLARE
       VN_BASE_NUM NUMBER := 3;   
       BEGIN
          FOR I IN 1..9
            LOOP
               
                DBMS_OUTPUT.PUT_LINE(VN_BASE_NUM ||'*'||I||'='|| VN_BASE_NUM * I);
                IF I = 3 THEN
                   GOTO FOURTH;
                    END IF;
                END LOOP;
                   
          <<FOURTH>>
          VN_BASE_NUM := 4;
          FOR I IN 1..9
            LOOP
               DBMS_OUTPUT.PUT_LINE(VN_BASE_NUM ||'*'||I||'='|| VN_BASE_NUM * I);
               END LOOP;
             END;

 

첫번째 포문에서 두번째 포문에 <<FOURTH>>라는 라벨을 붙였다. 그리고 첫번째 포문에서 인덱스 값이 3이 나오면  <<FOURTH>> 라벨로 이동해 3단을 출력하다가 4단을 출력하는 쿼리다.

 

 

NULL

NULL 문은 보통 IF문이나 CASE 문을 작성할때 주로 사용하는데 조건에 따라 처리 로직을 처리 로직을 작성하고 앞에서 작성한 모든 조건에 부합되지 않을때, 즉 ELSE 절을 수행할때 아무것도 처리 하지 않고 싶은 경우 NULL문을 사용한다.

IF VN_VARIABLE = 'A' THEN
  처리로직1;
  ELSIF VN_VARIABLE = 'B' THEN
    처리로직2;
    
    ELSE NULL;
    END IF;
    
    CASE WHEN VN_VARIABLE = 'A' THEN
          처리로직1;
         WHEN VN_VARIABLE = 'B' THEN
            처리로직2;
            
            ELSE NULL;
            
        END CASE;

 

반응형

'DB' 카테고리의 다른 글

Oracle PL/SQL[프로시저]  (0) 2020.12.26
Oracle PL/SQL 의 사용자 정의함수  (0) 2020.12.24
Oracle(PL/SQL) 구성요소  (0) 2020.12.24
Oracle(PL /SQL ) 기본구조  (0) 2020.12.23
Oracle(표현식)  (0) 2020.12.23