2012/03/27 13:25


1. 루프를 이용한 반복처리
  1.1 루프 기초
     1.1.1 루프 경계
루프를 시작하는 예약어,
루프 종료를 위한 조건, 루프 블록을 끝내는 END LOOP로 구성되어 있다.
     1.1.2 루프 바디
루프 반복 시 실행되는 루프 경계 안에 있는 일련의 실행 가능문이다.

  1.2 단순 루프
단수순 루프는 모든 루프 구성의 가장 기본이 되는 구조다. LOOP 키워드, 실행가능 코드 바디, END LOOP 키워드로 구성되어 있다.

 LOOP
    실행 가능문(들)
 END LOOP;

루프 경계는 LOOP와 END LOOP 예약어로만 구성되어 있으며 바디에는 적어도 실행 가능문 한개는 있어야 한다.

    1.2.1단순 루프 속성
 속성  설명
 루프 종료  단순 루프는 루프 바디에서 EXIT가 실행될 때 종료된다. EXIT가 실행되지 않는 경우, 단순 루프는 무한 루프가 된다.
 종료 검사 위치  루프 바디에서 (EXIT나 EXIT WHEN문이 실행되딜 때만) 검사된다. 단순 루프의 바디는 (또는 바디의 일부분) 적어도 한번은 실행된다.
 사용 이유  단순 루프는 다음과 같은 경우에 사용된다.
- 루프 실행 횟수를 알 수 없을 때
- 루프를 적어도 한 번은 실행하고 싶을 때

루프 경계에 해당 루프의 실행 여부를 판단하는 조건이 없기 때문에 맨 처음 항상 루프 바디가 실행됨으로 적어도 한번 실행하고자 할때 유용하다.

     1.2.2 단순 루프 끝내기
단순 루프처리를 강제적으로 끝내려면 루프 몸체에서 EXIT나 EXIT WHEN 을 실행하면된다
 EXIT;
 EXIT WHEN 조건;
조건은 불린 표현식이다.

* EXIT WHEN과 EXIT의 사용 시점
- 루프 종료 여부를 결정하는 단일 조건 표현식이 있을 때는 EXIT WHEN이 적합하다.
- 루프 종료 여부를 결정하는 조건이 여러 개이거나 여러 조건이 사용되는 루프에서 각 조건에 따라 '반환값'을 설정할 필요가 있을 때, IF나 CASE문을 사용하지 말고 해당 구문에서 하나 또는 하나 이상의 EXIT문을 사용하는게 좋다.

     1.2.3 REPEAT UNTIL 루프 대행
PL/SQL에는 루프 바디 실행 후 조건을 검사함으로써 항상 적어도 한번은 루프가 실행되게 보장하는 REPEAT UNTIL루프가 없다. 그러나 단순 LOOP로 REPEAT UNTIL을 대행할 수 있다.

 LOOP
    ...루프 바디 ...
    EXIT WHEN 불린_조건식;
 END LOOP;
불린 조건식은 불린 변수이거나 TRUE, FALSE가 되는 표현식이다.

  1.3 WHILE 루프
WHILE루프는 경계에 정의된 불린 조건이 TRUE가 되는 동안만 실행되는 조건 루프다. 조건에 따라 WHILE 루프 실행 여부가 결정되고 루프 실행이 고정적이지 않기 때문에 루프 실행 횟수를 미리 알수 없는 경우에 WHILE문을 사용하면 된다.

 WHILE 조건
 LOOP
    실행 가능문(들)
 END LOOP;

조건은 불린 변수이거나 TRUE, FALSE, NULL이 되는 표현식으로 루프 바디가 반복 실행될 때마다 조건이 검사된다.
조건이 FALSE나 NULL이면 루프를 종료하고 END LOOP문 다음 실행가능 문장으로 제어를 넘긴다.

    1.3.1 WHILE 루프 속성

 속성  설명
 루프 종료  WHILE 루프 경계의 불린 표현식이 FALSE나 NULL이 되면, WHILE루프는 종료된다
 종료 검사 위치  WHILE루프 조종료 검사는 루프 경계에 있다. 맨 처음 실행되기 전이나 바디가 실행되기 전마다 종료를 검사한다. 그래서 항상 한번은 루프가 실행된다고 보장하지 못한다.
 사용 이유  WHILE루프는 다음과 같은 경우에 사용된다
- 루프 바디 실행 횟수를 알 수 없을 때
- 루프를 조건적으로 종료하고 싶을 때
- 루프를 한 번도 실행할 필요가 없을 때

  1.4 숫자 FOR 루프
PL/SQL FOR 루프에는 숫자 FOR루프와 커서 FOR루프 두 가지가 있다.
숫자 FOR루프는 전형적인 FOR루프 형태로 카운트되는 루프다.
FOR루프의 반복 횟수는 루프가 시작될 때 알수 있는데 루프 경계의 FOR와 LOOP 키워드 사이에 있는 범위 스키마(range schema)에서 지정된다.

범위 스키마는 루프 인덱스(기존에 선언되지 않았을 경우)를 묵시적으로 선언하고, 범위의 시작점과 끝점을 지정하며 선택사항으로 루프 인덱스의 진행순서를 지정할 수도 있다.

 FOR loop index IN [REVERSE] 최저값 .. 최고값
 LOOP
    실행 가능문(들)
 END LOOP;
LOOP와 END LOOP 키워드 사이에 적어도 실행 가능문이 한개는 있어야 한다.

  1.4.1 숫자 FOR루프 속성

 속성  설명
 루프 종료  숫자 FOR 루프는 범위 스크마에 지정된 숫자가 되면 무조건 종료한다. EXIT문으로 루프를 종료할 수 있긴 하지만 추천하지 않는다.
 종료 검사 위치  각 루프 바디가 실행되고 나면 그때마다 PL/SQL은 루프 인덱스 값을 검사한다. 루프 인덱스가 범위 스키마 상한을 초과하면, 루프는 종료된다. 만약 하한이 범위 스키마의 상한보다 큰 경우, 루프 바디는 실행되지 않는다.
 사용 이유  고정된 횟수만큼 코드를 실행하고, 루핑을 너무 빨리 끝내고 싶지 않을 때 숫자 FOR루프를 사용하면 된다.

  1.4.2 숫자 FOR 루프의 사용 규칙
- 루프 인덱스를 선언하지 마라. PL/SQL은 자동적, 묵시적으로 루프 인덱스를 INTEGER형의 로컬 변수로 선언한다. 루프 인덱스의 영역은 루프 자체다. 바깥의 인덱스를 참조할 수 없다.
- 범위 스키마에서 사용된 표현식(최저값, 최고값)은 루프가 실행될 때 한번 판단된다. 루프가 실행될 때 범위는 다시 평가되지 않으며 루프 안에서 범위를 결정하는데 사용된 변수를 변경할 경우 적용되지 않는다.
- 루프 내부에서 인덱스나 범위 한계를 절대 변경하지 마라. 변경하면 PL/SQL은 컴파일 오류를 발생시키거나 변경작업을 무시할 것이다.
- 루프를 상한에서 하한으로 감소하고 싶을 때는 REVERSE 키워드를 사용하라. REVERSE 키워드를 사용해도 범위 지정의 첫번째 값이 두번째 값보다 작아야한다.

  1.4.3 증분 처리하기
PL/SQL은 특정 루프 인덱스 증분을 지정하는 'step' 문법을 지원하지 않는다. 숫자 FOR 루프의 모든 형태에서 루프는 항상 하나씩 증가되거나 감소한다.

1이 아닌 값으로 증분하고 싶은 경우 기술적 코드를 작성해야한다.
예를 들어 짝수일 경우에만 루프를 실행하고 싶을 경우
 FOR loop_index IN 1 .. 100
 LOOP
      IF MOD (loop_index, 2) = 0
      THEN
           /*  짝수이므로 계산 수행 */
          calc_values (loop_index);
      END IF;
 END LOOP;

 또는
 FOR even_number IN 1 .. 50
 LOOP
        calc_values (even_number*2);
 END LOOP;
첫번째의 경우 100번 실행되고 두번째의 경우 50번 실행된다.

  1.5 커서 FOR 루프
커서 FOR루프는 루프 경계에서 직저접적으로 사용된 명시적 커서나 SELECT문 관련 루프다. 커서의 모든 레코드를 각각 페치해서 처리해야 할 경우에만 커서 FOR루프를 사용한다.

    1.5.1 기본 문법

 FOR 레코드_인덱스 IN [커서명, (명시적 SELECT문) ]
 LOOP
    실행 가능 문장(들)
 END LOOP;
여기에서 '레코드_인덱스'는 [커서명]에 해당되는 커서를 바탕으로 하여 %ROWTYPE 속성으로 선언된 묵시적 레코드다.

    1.5.2 커서 FOR 루프 속성

 속성  설명
 루프 종료  커서 FOR 루프는 관련 커서의 모든 레코드가 페치되면 무조건 종료된다. 또한 EXIT문으로 종료할 수 있지만 추천하지 않는다
 종료 검사 위치  루프 바디가 실행될 때마다 PL/SQL은 페치 작업을 한다. 커서의 %NOTFOUND 속성이 TRUE가 되는 경우 루프는 종료된다. 커서가 아무행도 반환하지 않으면 루프는 바디를 실행하지 않는다.
 사용 이유  커서의 모든 레코드를 페치해서 처리할때, 커서 FOR루프를 사용한다.

    1.5.3 커서 FOR 루프 예제
 DECLARE
   CURSOR occupancy_cur IS                            -- 커서 선언
     SELECT pet_id, room_number
     FROM occupancy WHERE occupied_dt = TRUNC( SYSDATE;)
   occupancy_rec occupancy_cur%ROWTYPE;    -- 커서를 위한 레코드 명시적 선언
 BEGIN
   OPEN occupancy_cur;                                  -- 커서 열기
   LOOP                                                          -- 무한 루프 시작
     FETCH occupancy_cur INTO occupancy_rec; -- 한행씩 페치해 레코드에 넣기
     EXIT WHEN occupancy_cur%NOTFOUND;     -- 커서 속성 검사
     update_bill(occupancy_rec.pet_id, occupancy_rec.room_number);   -- 작업 수행
   END LOOP;
   CLOSE occupancy_cur;                                -- 커서 닫기
 END;

 위 PL/SQL 블록을 커서 FOR루프로 바꾸면 다음과 같다
 DECLARE
   CURSOR occupancy_cur IS
     SELECT pet_id, room_number
     FROM occupancy WHERE occupied_dt = TRUNC( SYSDATE;)
 BEGIN
   FOR occupancy_rec IN occupancy_cur
   LOOP
     update_bill(occupancy_rec.pet_id, occupancy_rec.room_number);
   END LOOP;
 END;

앞부분 예제에서 레코드선언, OPEN문, FETCH문, CLOSE문, %FOUND 속성 검사 부분이 제거되었다.

  1.6 루프 레이블
레이블을 이용해 루프에 이름을 붙일 수 있다.
선택적으로 END LOOP 예약어 뒤에 레이블이 올 수도 있다.
 <<year_loop>>
 WHILE year_number <= 1995
 LOOP
   <<month_loop>>
    FOR month_number IN 1 .. 12
    LOOP
        . . .
    END LOOP month_loop;
 END LOOP year_loop;

- 긴 바디를 사용하는 루프를 작성하는 경우 루프 앞과 뒤를 명시적으로 묶기 위해 루프 레이블을 사용하면 관리나 디버그 작업을 더 쉽게 할 수 있다.
- 루프 인덱싱 변수명을 한정하기 위해 루프 레이블을 사용할 수 있다.

저작자 표시 비영리 변경 금지
Posted by Cocooning
2012/03/27 11:33

1. 조건제어와 순차제어
  1.1 IF문
     1.1.1 IF-THEN 조합

 IF 조건
 THEN
  . . . 일련의 실행 가능한 문장 . . .
 END IF;

불린 변수나 상수 또는 TRUE, FALSE, NULL이 되는 표현식 등이 조건으로 올 수 있다. 조건이 TRUE로 판단되면 THEN과 END IF 사이의 코드가 실행된다.조건이 FALSE나 NULL이 되면, 어떤 처리도 이루어지지 않는다.

     1.1.2 IF-THEN-ELSE 조합
두 가지 상호 배제적인 처리를 원할 때 IF-THEN-ELSE를 사용하면 된다.
IF-THEN-ELSE로 either/or 로직을 처리할 수 있는데 관련 문법은 다음과 같다.

 IF condition
 THEN
   . . . TRUE 일련의 실행 가능한 문장 . . .
 ELSE
   . . . FALSE/NULL 일련의 실행 가능한 문장 . . .
 END IF;

불린 변수,상수, 표현식이 조건으로 올 수 있다. 조건이 TRUE인 경우 THEN과 ELSE 사이의 코드가 실행된다.

* 불린 플래그
하나 이상의 동일한 불린 표현식을 사용하지 않아도 되기 때문에, 불린 변수를 플래그로 사용하면 편하다. 플래그로 사용할 때는 불린 표현식 결과가 직접적으로 변수로 할당된다.

 IF :customer.order_total > max_allowable_order
 THEN
 order_exceeds_balance:= TRUE;
 ELSE
 order_exceeds_balance := FALSE;
 END IF;

 다음 처럼 작성하는 것이 더 단순하다.
 order_exceeds_balance := :customer.order_total > max_allowable_order;

     1.1.3 IF-THEN-ELSIF 조합
여러 처리 방식이 있을 때 유용하며, either/or 방식으로 처리하는 것이 아니다.
IF-ELSIF는 상호 배제 대안 여러 개를 처리할 수 있게 해준다.
 IF 조건-1
 THEN
    문장들-1
 ELSIF 조건-N
 THEN
    문장들-N
 [ELSE
    else_문장들]
 END IF;

각 ELSIF절에서는 조건 다음에 THEN을 사용해야 하지만, ELSE 키워드는 THEN을 사용하지 않는다.
어떤 조건에도 TRUE가 되지 않는 경우 ELSE절의 문장이 실행된다. 그러나 ELSE절의 문장은 선택사항이다.
IF-ELSE의 각 조건은 제일 위에서부터 순차적으로 검사되며 조건 두개에서 TRUE가 발생될 경우 TRUE가 되는 첫번째 조건 관련 코드를 실행한다.
IF-THEN-ELSIF 보다는 오라클 9i부터 사용 가능한 CASE문이 더 효과적으로 처리 가능하다.

     1.1.4 중첩 IF문
IF문 안에 또 다른 IF문을 중첩해서 사용할 수 있다.

 IF 조건1
 THEN
   IF 조건2
   THEN
      문장들2
   ELSE
     IF 조건3
     THEN
        문장들3
     ELSIF 조건4
     THEN
         문장들4
     END IF;
   END IF;
 END IF;

중첩 루프와 유사한 중첩 IF문은 파악하기 힘들고 디버그하기도 힘들다. 3단계 보다 더 깊이 중첩할 필요가 있는 경우는 로직을 다시 검토하고 간단히 처리할 방법을 알아보는 것이 좋다. 그래도 방법이 없다면 최하위 IF문을 감출 수 있는 하나 또는 그 이상의 모듈 생성을 고려해 본다.

중첩 IF문을 사용하는 이유는 하나의 조건이 참일 경우만 다른 조건을 판단하게 하기 위해서다. 조건 판단 비용이 CPU나 메모리 활용 면에서 비쌀 때 중첩IF문을 사용하게 되면 자주 실행되거나 빠른 응답 시간이 요구되는 코드인 경우 조건 판단을 안쪽 IF문으로 미룸으로써 필요한 경우에만 실행하게 되는 이점이 있다.

* 문법사용시 체크할 것
- 항상 IF와 END IF를 매칭 시킨다
- END와 IF 키워드 사이에 공백을 둔다
- ELSIF 키워드에는 'E'가 없다
- END IF 키워드 다음에만 세미콜론(;)을 사용한다

  1.2 CASE문
CASE문은 1992년에 SQL 표준이 되었지만, 오라클의 SQL에서는 오라클 8i 릴리스부터 pl/sql에서는 오라클 9i부터 CASE문을 지원한다.

     1.2.1 단순 CASE문
하나의 값에 일련의 PL/SQL문을 연결짓는다. 해당 값 중 하나를 반환하는 표현식을 이용하여 실행할 코드를 결정한다.

 CASE 표현식
 WHEN 결과값1 THEN
   문장들1
 WHEN 결과값2 THEN
   문장들2
 . . .
 ELSE
   문장들_else
 END CASE;

CASE문을 판단할 때 PL/SQL은 먼저 표현식을 판단한다. 그 다음 결과값을 비교한다.
ELSE절은 선택사항이다. 명시하지 않을 경우 다음과 같이 처리한다.
 ELSE
   RAISE CASE_NOT_FOUND;

ELSE절을 지정하지 않고 표현식의 결과 값이 들어맞는 WHEN절이 없을 경우 CASE_NOT_FOUND 오류를 발생한다. 조건이 없을경우 아무처리도 하지않는 IF문과는 다른점이다.

     1.2.2 검색된 CASE문
불린 조건 리스트를 판단해서 실행할 코드를 결정한다. TRUE로 판단된 첫번째 조건과 관련된 일련의 문장이 실행된다.

 CASE
 WHEN 표현식1 THEN
   문장들1
 WHEN 표현식2 THEN
   문장들2
 . . .
 ELSE
   문장들_else
 END CASE;

단순 CASE문처럼, 검색된 CASE문도 다음 규칙을 따른다
- 일련의 문장이 실행되면 실행은 종료된다. 하나 이상의 표현식이 TRUE가 되는 경우 TRUE가 된 표현식 중 첫번째 표현식과 관련된 문장만 실행한다.
- ELSE절은 선택사항이며 명시되지 않았고 TRUE가 되는 표현식이 없는 경우 CASE_NOT_FOUND 예외가 발생한다.
- WHEN절 조건은 위에서 부터 아래로 순차적으로 판단된다.

* WHEN절 조건이 순차적으로 판단되기 때문에 가능성 있는 WHEN절을 앞에 둬서 코드를 작성하면 효율성을 높일 수 있다. 또한 중첩 IF문에서 처럼 판단조건이 비쌀경우 해당 WHEN절을 뒷부분에 둬서 조건 판단이 될 가능성을 최소화 할 수 있다.

     1.2.3 중첩 CASE문
CASE문도 IF문처럼 중첩될 수 있으며 CASE문에서는 어떤 구문이든 사용할 수 있으므로 안쪽에 IF문을 사용할 수도 있다.

     1.2.4 CASE 표현식
CASE문이 문장으로 처리하는 것을 CASE표현식은 표현식으로 처리한다.
어떤 표현식을 사용하든지 간에, CASE 표현식은 단일 값을 반환한다. WHEN절의 결과값 표현식은 여러 문장이 아니라 표현식 한개다.
CASE 표현식의 끝을 나타내기 위해 세미콜론이나 END CASE가 아니라 END를 사용한다.
CASE문과는 달리 CASE 표현식에서는 맞는 조건이 없는 경우 오류가 발생하지 않는다. 대신 NULL을 반환한다.

 단순 CASE 표현식 :=
 CASE 표현식
 WHEN 결과값1 THEN
   결과값 표현식1
 WHEN 결과값2 THEN
   결과값 표현식2
 . . .
 ELSE
   결과값 표현식_else
 END;

 검색된 CASE 표현식 :=
 CASE
 WHEN 표현식1 THEN
   결과값 표현식1
 WHEN 표현식2 THEN
   결과값 표현식2
 . . .
 ELSE
   결과값 표현식_else
 END;


  1.3 GOTO문
GOTO문은 동일 PL/SQL 블록의 실행절에서 다른 실행 가능 문장으로 무조건 분기한다.
일반적 형식은 다음과 같다
 GOTO 레이블명;

레이블 명은 대상 문장을 지정하는 레이블의 이름이다. 레이블 정의는 다음과 같다.
 <<레이블명>>

     1.3.1 GOTO문 제약사항
         - 레이블에는 반드시 실행가능 문장이 한 개 이상 있어야 한다.
         - 대상 레이블은 GOTO문과 동일한 영역에 있어야 한다.
           다음 구문들은 나름대로의 영역이 있다.
           - 함수, 프로시저, 익명블록, IF문, LOOP문, 예외처리, CASE문
         - 영역 밖의 레이블로 분기하려고 하면 오류가 발생한다.
 EX) 조건이 TRUE인 경우에만 IF문이 실행되므로  FALSE일 경우 오류가 발생한다. 
       각 구문은 나름의 영역이 있기 때문에 하나의 IF구문에서 다른 구문으로 분기할 수 없다. 
       CASE문 또한 한 구문에서 다른 구문으로 분기할 수 없다.
       루프 중간으로 분기할 수 없다.
       로컬 모듈로 분기할 수 없다.( 블록의 주 바디에서 해당 블록에서 정의되딘 함수, 프로시저, 다른 모듈의 레이블로 분기할 수 없다.)
                      
  1.4 NULL문
아무런 처리를 하지 말아야 할 경우 NULL문을 사용한다.
NULL문은 단수순히 세미콜론이 붙은 예약어 NULL이다. 세미콜론은 해당 문장이 NULL값이 아니라 문장임을 나타내기 위해 사용된다.

     1.4.1 예외 취소하기
예외부에는 예외 처리기가 하나 또는 한개 이상이 있는데 예외 처리를 위해 따로 코드를 작성하고 싶지 않다면 오류가 발생했을 때 PL/SQL블록 실행을 중단시키면서 어떤 오류든지 개폐블록으로 전달하지 않기 위해 NULL문장을 사용한다.
 예외부의 구조
 EXCEPTION
   WHEN 예외명1
   THEN
       실행 가능 문장들;
   WHEN 예외명N
   THEN
       실행 가능 문장들;
   WHEN OTHERS
   THEN
       실행 가능 문장들;
 END;

     1.4.2 레이블에서 NULL 사용하기
레이블 <<레이블명>>에 NULL문을 사용하여 레이블에는 적어도 실행 가능문이 한 개는 있어야 된다는 조건을 만족시키면서 GOTO문에서 레이블을 이용하여 분기하도록 할 수 있다.

저작자 표시 비영리 변경 금지
Posted by Cocooning
2012/03/26 18:57

PRAGMA는 정보를 컴파일러에 전달하는 기능만 한다.

PRAGMA 키워드 관련 문법은 다음과 같다.
PRAGMA 명령어;

명령어는 컴파일러에 지시를 하는 문장이다. 선언부 어디서든지 이런 지령을 PL/SQL 컴파일러에 전달할 수 있다.

프라그마 종류는 다음과 같다.

- AUTONOMOUS_TRANSACTION
  주 트랜잭셔션이나 외부 트랜젝셔션에 영향을 미치지 않고 현재 블록 내부에서 발생한 데이터베이스 변경사항을 커밋하거나 롤백하게 정보를 전달한다.

- EXCEPTION_INIT
  특정 오류 번호를 프로그램에서 예외로 선언된 식별자와 연관하게 정보를 전달한다.

- RESTRICT_REFFERENCES
  패키지 프로그램의 순수 레벨(부작용이 없는 상태) 정보를 전달한다

- SERIALLY_REUSABLE
  패키지 레벨 데이터가 해당 데이터의 참조 사이에 존속하지 않아야함을 전달한다.
저작자 표시 비영리 변경 금지
Posted by Cocooning

티스토리 툴바