/*  커서(cursor) : 쿼리문에 의해서 반환되는 결과값들을 저장하는 메모리 공간
    Fetch : 커서에서 원하는 결과값을 추출하는 것
    
    - 커서의 종류
      - 명시적(Explicit) 커서 : 사용자가 선언 후 사용하는 SQL 커서,
                              주로 여러개의 행을 처리하고자 할 경우 사용
      - 묵시적(Implicit) 커서 : 오라클에서 자동으로 선언해주는 SQL 커서,
                              사용자는 생성 유무를 알 수 없다. 한 행만 처리 가능.
                              
    - 커서의 속성
      %Found - 할당할 레코드가 있는 경우 true 반환
      %isOpen - 커서가 오픈 상태일 경우 true 반환
      %NotFound - 할당할 레코드가 없는 경우 true 반환
      %RowCount - 카운터 역할. 오픈 됐을 경우 0, 패치 발생할 때마다 1씩 증가

    - 커서의 처리단계(명시적 커서)
      1. 명시적 커서 선언      -> Cursor 커서 이름
      2. 명시적 커서 오픈      -> Open 커서이름
      3. 커서에서 데이터 추출   -> Fetch 커서이름
      4. 커서 종료            -> Close 커서이름
      
*/

set serveroutput on;


declare
  emp_id number(4); -- 변수 선언
  emp_name varchar2(10);
  emp_salary number(10);
  
  Cursor cu1 is 
    select employee_id, last_name, salary
    from employees
    where department_id = 50;
  
begin
  open cu1;
  
  dbms_output.put_line('사번  이름  급여');
  
  loop
    fetch cu1 into emp_id, emp_name, emp_salary; -- 커서에서 값을 꺼내오는(추출) 것
    exit when cu1%notFound;
  
    dbms_output.put_line(emp_id||' '||emp_name||' '||emp_salary);
  end loop;
  close cu1;  -- 커서 닫기
  
end;
/

/* 커서와 반복문(For문) 
   - 사용 형식
  For 레코드 네임 IN 커서 이름 LOOP
    명시적 커서의 OPEN, FETCH 가 자동으로 수행
    실행 문장들
  END LOOP; -- 루프문을 빠져나갈 때 자동적으로 커서가 종료됨

*/

declare
  cursor emp_cur is
    select employee_id, last_name
    from employees;
begin
  for emp_rec in emp_cur loop
    dbms_output.put_line(emp_rec.employee_id||' '||emp_rec.last_name);
  end loop;

end;
/

declare
  emp employees%rowType;
  
  cursor cur1 is
    select employee_id, last_name, salary
    from employees;

begin
  for emp in cur1 loop
    exit when cur1%notfound;
    dbms_output.put_line(emp.employee_id||' '||emp.last_name||' '||emp.salary);
  end loop;
  
end;
/


declare 

begin
  for emp in(select employee_id, last_name, salary
            from employees) -- 커서명 대신 바로 쿼리를 써준다(묵시적 커서)
    loop
      dbms_output.put_line(emp.employee_id||' '||emp.last_name||' '||emp.salary);
  end loop;
end;
/


/* 묵시적 커서 사용 예 : 속성 사용시 
                      SQL%notfound, SQL%rowcount, SQL%found, SQL%isopen 등의 형태로 사용 
*/

declare
  cnt1 number;
  cnt2 number;
  
begin
  select count(*) into cnt1
  from employees
  where department_id = 50;
 
  cnt2 := sql%rowcount; -- 묵시적 커서의 경우 속성 사용시 커서이름 자리에 sql이 들어간다
                        -- fetch 할 때마다 1씩 값이 증가
  dbms_output.put_line('cnt1의 값 : '||cnt1); -- count(*)의 값
  dbms_output.put_line('cnt2의 값 : '||cnt2); -- count(*)의 값을 커서에 넘겨준 횟수(fetch 발생 횟수)
  
end;
/

+ Recent posts