PL/SQL 에서는 다른 프로그래밍 언어와 마찬가지로 여러 종류의 제어 구문을 활용하여 PL/SQL 블록 안에서 논리적인 흐름을 변경할 수 있다.
위와 그림과 같이 True 가 되어 THEN 구문을 실행하고 그렇지 않을 경우에는 FALSE 가 되어 ELSE 구문을 실행하는 구조이다.
IF 문의 마지막은 END IF로 마무리하면 됩니다.
조건 비교가 추가로 필요하다면 IF 또는 ELSE 문 안에 IF 문을 추가로 사용할 수 있다
--조건이 하나일 경우
IF condition THEN
sequence of statments1;
END IF;
--하나의 조건과 그 외의 조건의 경우
IF condition THEN
sequence of statments11;
ELSE
sequence of statments3;
END IF;
--여러 개의 조건의 경우(ELSIF)
IF condition1 THEN
sequence of statments11;
ELSIF condition1 THEN
sequence of statments2;
ELSE
sequence of statments3;
END IF;
DECLARE
I_SALES NUMBER := 2500;
I_BONUS NUMBER;
BEGIN
--I_SALES 가 3000이상일 경우
IF I_SALES >= 3000 THEN
I_BONUS := 10000;
--I_SALES가 1000이상일 경우
ELSIF I_SALES >= 1000 THEN
I_BONUS := 5000;
ELSE I_BONUS := 1000;
END IF;
--I SALES 가 2500 이므로 두 번째 ELSEIF 문이 수행되며 I_BONUS 변수에 5000이 입력됨
DBMS_OUTPUT.PUT_LINE('BONUS: ' || I_BONUS);
-- I SALES 가 3000 이하이면서 I_BONUS가 100이상일경우
--IF 문 안에 또 다른 IF문을 사용하여 두 가지 조건을 비교할 경우
IF I_SALES < 3000 THEN
IF I_BONUS > 100 THEN
I_BONUS := 2000;
END IF;
END IF;
DBMS_OUTPUT.PUT_LINE('bonus: ' || I_BONUS);
END;
CASE 문
선택 사항이 많을 경우 IF문을 사용하면 매우 복자해지고 가독성도 떨어집니다. 이런경우 CASE구문을 사용하여 여러 조건에 대한 민족 여부를 간단하게 구현할 수 있습니다.
CASE 함수를 이용하여 조건 만족 여부를 확인할 때 차례로 순차적으로 비교하게 되며 첫 번째로 만족하는 조건문이 발견되면 그 이후의 조건문은 수행되지 않습니다. 따라서 선택될 확률이 높은 조건을 앞쪽에 위치시키는 것이 좋으며, 만약 만족하는 값이 하나도 없으면 ELSE 키워드를 이용하여 기본 값을 설정할수 있다.
DECLARE
SALARY NUMBER := 1500;
I_OUT VARCHAR2(20);
BEGIN
I_OUT :=
CASE
WHEN SALARY > 2000 THEN 'Excellent'
WHEN SALARY > 1000 THEN 'VertGood'
WHEN SALARY > 500 THEN 'GOOD'
ELSE 'NotBad'
END;
DBMS_OUTPUT.PUT_LINE('SALARY' || SALARY || 'IS' || I_OUT);
END;
LOOP
반복해서 프로그램을 수행해야 할 경우에는 LOOP 구문을 사용할수 있다.
기본 LOOP구무은 종료 조건을 주지 않으면 무한 루프에 빠질 수 있기 때문에 주의해야 한다
LOOP를 돌다가 특정한 조건에서 빠져 나오기 위해서 EXIT WHEN 구문을 사용한다
LOOP
EXITWHEN exit_condition;
END LOOP;
아래는 루프가 돌다가 100번째 수행 시 종료되도록 한예이다.
DECLARE
I_CNT NUMBER := 1;
BEGIN
--LOOP를 돌며 clob 데이터 출력
LOOP
--틀정한 조건을 빠저나오기위해
EXIT WHEN I_CNT > 100;
DBMS_OUTPUT.PUT_LINE('CNT : ' || I_CNT);
I_CNT := I_CNT + 1;
END LOOP;
END;
DECLARE
--SUBTYPE 을 이용한 새로운 변수 타입 설정
SUBTYPE COUNT_TYPE IS NUMBER(3);
I_CNT COUNT_TYPE NOT NULL := 0;
BEGIN
--goto 활용을 위한 other 레이블 설정
<<outher>>
LOOP
DBMS_OUTPUT.PUT_LINE('OTHER LOOP' || i_cnt);
--INNER 레이블 설정
<<iinner>>
LOOP
I_CNT := I_CNT + 1;
DBMS_OUTPUT.PUT_LINE('INNER LOOP : COUNT = ' || I_CNT);
--I_CNT 5가되면 other 레이블 밖으로 빠저나감
EXIT outher WHEN I_CNT = 5;
--I_CNT 3되면 이전 루프 밖으로 빠저나감
EXIT WHEN I_CNT =3;
END LOOP;
--I_CNT 100이되면 이전 루프 밖으로 빠저나감
EXIT WHEN I_CNT >= 100;
3이되면 여기로 오고 나서 다시 inner로 돌아가서 4부터 시작함
DBMS_OUTPUT.PUT_LINE('outherLoop2 : I_COUNT = ' || I_CNT);
END LOOP;
5가되면 outher 레이블로 바쩌나옴
DBMS_OUTPUT.PUT_LINE('outherLoop3 : I_COUNT = ' || I_CNT);
GOTO FINAL;
DBMS_OUTPUT.PUT_LINE('NEVER EXECUTED!!');
<<final>>
DBMS_OUTPUT.PUT_LINE('FINAL');
RETURN;
DBMS_OUTPUT.PUT_LINE('NEVER EXECUTED!!');
END;
/
결과를 보면 카운터 값이 3이 될때 까지 안쪽 LOOP가 수행이 되고 3이 되면 안쪽 루프를 빠져나와 바깥쪽 LOOP가실행된다.
카운터가 5가 되면 EXIT outher WHEN 구문이 실행되고 모든 LOOP에서 빠저나온다.
while loop
While loop은 exit 조건이 while 절에 위치해 있다는것을 제외하고는 기본 loop와 거의 유사하다
while절에 기술한 조건이 True일 동안 loop 안의 로직이 반복 수행된다.
DECLARE
I_CNT NUMBER := 0;
BEGIN
WHILE I_CNT = 3 LOOP
UPDATE EMP SET D_COMM = 0 WHERE EMPNO = 7900 + I_CNT;
I_CNT := I_CNT + 1;
END LOOP;
ROLLBACK;
END;
FOR LOOP
For Loop 에서는 변수를 선언하고 1씩 증가하는 로직을 추가하지 않아도 내부적으로 알아서 처리한다.
IN 절 다음에 하위값(lower_bound)과 상위 값(upper_bound) 을 기술하면 해당 횟수만큼 루프를 실행한다
For loop 안의 IN 절에 커서를 사용할 수도 있는데 이 경우에는 커서의 결과 건수만큼 수행된다.
FOR loop_index IN lower_bound .. upder_bound
LOOP
body of loop
END LOOP;
BEGIN
FOR I IN 1..20
LOOP
SELECT NVL(MAX(ENAME),'NULL')
INTO I_ENAME
FROM EMP
WHERE EMPNO = 7899 + I;
DBMS_OUTPUT.PUT_LINE('ENAME :' || I_ENAME);
END LOOP;
END;
BEGIN
FOR I IN REVERSE 1..20
LOOP
SELECT NVL(MAX(ENAME),'NULL')
INTO I_ENAME
FROM EMP
WHERE EMPNO = 7899 + I;
DBMS_OUTPUT.PUT_LINE('ENAME :' || I_ENAME);
END LOOP;
END;
커서 ForLoop
For LOOP 와 유사하나 반복 횟수를 정하는 lower_bound , upper_bound 가 사용되지 않아도 되며
커서 또는 SQ을 실행하여 추출 되는 결과 수만큼 반복 수행이 된다.
FOR recod_index IN cursor_name
LOOP
body of loop
END Loop;
DECLARE
--부서별 사원 정보를 추출하는 커서 선언
CURSOR emp_cursor(p_deptno NUMBER)
IS
SELECT ENAME,EMPNO
FROM EMP
WHERE DEPTNO = P_DEPTNO;
BEGIN
--커서 결과 건수만큼 LOOP 가 수행됨
--emp_cursor 커서에 10번 부서로 조회하여 emp_rec 레코드 변수에 저장
FOR emp_rec IN emp_cursor(10)
LOOP
--emp_rec 레코드의 값을 출력 레코드 칼럼 이름으로 출력
DBMS_OUTPUT.PUT_LINE('EMP NAME:' || EMP_REC.ENAME);
DBMS_OUTPUT.PUT_LINE('EMPNO:' || EMP_REC.EMPNO);
END LOOP;
END;
SELECT문을 CUROSR로 선언한 emp_cursor에 담고 FOR 에서 10번 부서로 조회하며 emp_rec 레코드 변수에 저장
하면서 10번부서에 해당하는 사원의 이름과 사번을 출력하는 쿼리다.
DECLARE
BEGIN
--커서 결과 건수만큼 LOOP 가 수행됨
--emp_cursor 커서에 10번 부서로 조회하여 emp_rec 레코드 변수에 저장
FOR emp_rec IN (
SELECT ENAME,EMPNO
FROM EMP
WHERE DEPTNO=10)
LOOP
--emp_rec 레코드의 값을 출력 레코드 칼럼 이름으로 출력
DBMS_OUTPUT.PUT_LINE('EMP NAME:' || EMP_REC.ENAME);
DBMS_OUTPUT.PUT_LINE('EMPNO:' || EMP_REC.EMPNO);
END LOOP;
END;
또는 커서대신에 IN 절 옆에 사용자 정의 하는 방법으로도 사용할수 있다.
'DB' 카테고리의 다른 글
Oracle PL/SQL 자율 트랜잭션 (0) | 2021.01.05 |
---|---|
OraclePL/SQL [커서 관리] (0) | 2021.01.03 |
Oracle PL/SQL 프로시저[패키지] (0) | 2021.01.02 |
Oracle SQL(서브쿼리) (0) | 2020.12.31 |
Oracle PL/SQL [함수] (0) | 2020.12.31 |