2016년 7월 28일 목요일

[IT실무고급교육★탑크리에듀]오라클 명시적 커서(Explicit Cursor)


오라클 명시적 커서(Explicit Cursor) 

 멀티 로우를  SELECT 하기위해 사용한다. 
 선언(Declaring) : Declare 섹션에서 정의한다. 메모리 초기화 단계이며 커서에 이름을 부여하고 SELECT문장을 정의하며, SELECT문에는 INTO 절이 필요없다. 
CURSOR c_emp IS SELECT * FROM emp; 
 오픈(Opening) : SQL문장을 실행하고 커서를 위한 메모리를 할당하며 BEGIN 절에서 실행한다. 커서는 SELECT된 데이터(Active Set)의 첫번째 레코드에 포인터가 위치하고 패치단계에서 사용할 수 있게 된다. OPEN시 실행되는 SQL문장에서 추출되는 레코드가 없더라도 오류가 발생하지 않고 데이터가 없다는 것은 이후 FETCH를 마친 후 커서 속성값을 통해 판단 할 수 있다.(%FOUND) 
OPEN c_emp; 
 패치(Fetching) : 데이터 추출단계이며 FETCH되는 레코드가 없더라도 오류가 발생하지 않는다. INTO절 다음에 오는 칼럼 리스트는 SELECT시 정의한 칼럼 리스트와 개수, 타입이 동일해야 한다. “SELECT *” 등으로 커서를 만들었다면 %ROWTYPE을 적절히 이용하면 된다. 
FETCH c_emp INTO c_emp_record; 
 종료(Closing) : 커서 Closing 
CLOSE c_emp; 

[명시적 커서의 속성] 
커서이름%ISOPEN : 커서가 오픈되었으면 TRUE 
커서이름%FOUND : FETCH했는데 레코드가 있었으면 TRUE 
커서이름%NOTFOUND : FETCH했는데 레코드가 없었으면 TRUE 
커서이름%ROWCOUNT : 지금까지 FETCH한 데이터 건수 

%FOUND %ISOPEN %NOT FOUND %ROWCOUNT 
OPEN 전 오류 FALSE 오류 오류 
  후 NULL TRUE NULL 0 
First FETCH 전 NULL TRUE NULL 0 
  후 TRUE TRUE FALSE 1 
Next FETCH(es) 전 TRUE TRUE FALSE 1 
  후 TRUE TRUE FALSE 패치한 건수 
Last FETCH 전 TRUE TRUE FALSE 패치한 건수 
  후 FALSE TRUE TRUE 패치한 건수 
CLOSE 전 FALSE TRUE TRUE 패치한 건수 
  후 오류 FALSE 오류 오류 

SQL> SET SERVEROUTPUT ON 
SQL> DECLARE 
      CURSOR c_emp IS 
      SELECT ename, sal FROM emp WHERE deptno = 10; 
      v_ename emp.ename%TYPE; 
      v_sal  emp.sal%TYPE; 
    BEGIN 
      OPEN c_emp; 
      LOOP 
          FETCH c_emp INTO v_ename, v_sal; 
        EXIT WHEN c_emp%NOTFOUND OR c_emp%NOTFOUND IS NULL; 
        DBMS_OUTPUT.PUT_LINE(c_emp%ROWCOUNT || '. ' || v_ename || ',' || v_sal); 
      END LOOP; 
      CLOSE c_emp; 
  END; 
  / 

1. CLARK,2837 
2. KING,5789 
3. MILLER,1505 

-- CURSOR FOR LOOP는 커서의 레코드를 알아서 다 처리해주므로 EXIT WHEN이 필요없다 
-- 알아서 OPEN하고 알아서 FETCH, Closing 한다. 즉 선언만 하여 사용하면 된다. 
SQL> DECLARE 
      CURSOR c_emp IS 
      SELECT ename, sal FROM emp WHERE deptno = 10; 
    BEGIN 
      FOR emp_record IN c_emp LOOP 
          DBMS_OUTPUT.PUT_LINE(c_emp%ROWCOUNT || '. ' 
              || emp_record.ename || ',' || emp_record.sal); 
      END LOOP; 
    END; 
  / 

1. CLARK,2837 
2. KING,5789 
3. MILLER,1505 

-- 아래와 같이 커서 정의를 CURSOR FOR LOOP헤더에서 해도 된다. 
-- 물론 커서이름이 없으니 커서의 속성은 사용하지 못한다. 
SQL> DECLARE 
    BEGIN 
      FOR emp_record IN (SELECT ename, sal FROM emp WHERE deptno = 10) LOOP 
          DBMS_OUTPUT.PUT_LINE(emp_record.ename || ',' || emp_record.sal); 
      END LOOP; 
    END; 
  / 

CLARK,2837 
KING,5789 
MILLER,1505

댓글 없음:

댓글 쓰기