PLSQL - 04, 커서

스텔스 커서
스텔스 커서 의 속성:
  • SQL% ROWCOUNT 가 성공 적 으로 작 동 한 줄 의 수
  • SQL% FOUND 에서 복합 조건 을 발견 한 줄 을 TRUE 로 되 돌려 줍 니 다
  • SQL% NOTFOUND 에서 복합 조건 을 발견 하지 못 한 행 회 TRUE
  • SQL% ISOPEN 커서 열기 상태 (boolean)
  • 데모: 암시 적 커서 속성 인쇄
    declare
      v_count number;
    begin
      select count(*) into v_count from scott.emp;
      dbms_output.put_line(chr(10)||'select return '||sql%rowcount||' rows!');
    end;
    /
    
    begin
      delete emp;
      dbms_output.put_line(chr(10)||sql%rowcount||' rows deleted!'); 
      rollback; 
    end;
    /

    현식 커서
    현식 커서 사용 절차:
  • 선언 성명: 커서 c1 을 정의 하 는 것 은 ename, sal from emp 입 니 다.
  • open 열기: 열 어야 상기 조회 문 구 를 실행 할 수 있 습 니 다
  • fetch 가 져 오기: 메모리 에서 한 줄 씩 가 져 오고 한 줄 이 적 습 니 다
  • close 닫 기: 닫 지 않 으 면 메모 리 를 계속 차지 합 니 다
  • 연습 1: 기본 loop 순환 + 커서 사용 표시
    DECLARE
      v_empno employees.employee_id%TYPE;
      v_ename employees.last_name%TYPE;
      CURSOR emp_cursor IS SELECT employee_id, last_name FROM employees; --  
    BEGIN
      OPEN emp_cursor; --  
      LOOP
        FETCH emp_cursor INTO v_empno, v_ename; --  
        exit when emp_cursor%rowcount>20;
        DBMS_OUTPUT.PUT_LINE (TO_CHAR(v_empno)||' '|| v_ename);
      END LOOP;
      CLOSE emp_cursor; --  
    END ;
    /

    연습 2: for 순환 + 커서 사용 표시
    DECLARE
      v_empno employees.employee_id%TYPE;
      v_ename employees.last_name%TYPE;
      CURSOR emp_cursor IS SELECT employee_id, last_name FROM employees;
    BEGIN
      OPEN emp_cursor;
      FOR i IN 1..10 LOOP        --  i     
        FETCH emp_cursor INTO v_empno, v_ename;
        DBMS_OUTPUT.PUT_LINE (TO_CHAR(v_empno)||' '|| v_ename);
      END LOOP;
      CLOSE emp_cursor;
    END ;
    /

    커서 for 순환: 열기, 가 져 오기, 닫 기 동작 을 생략 할 수 있 습 니 다.
    declare 
      cursor emp_cursor is select rownum,employee_id,last_name from employees; --  
    begin
      for emp_record in emp_cursor loop --                  i record  
        exit when emp_cursor%rowcount>23;
          dbms_output.put_line(emp_record.rownum||' '||
                               emp_record.employee_id||' '||
                               emp_record.last_name);
      end loop; --    
    end;
    /

     
    커서 정의 생략
    커서 의 정 의 를 생략 하고 for... in 에서 조 회 를 사용 할 수 있 습 니 다.그러나 커서 제어, 예 를 들 어% rowcount 등 을 사용 할 수 없습니다. 커서 이름 이 정의 되 지 않 았 기 때 문 입 니 다.따라서 커서 의 속성 을 사용 하려 면 정의 가 없어 서 는 안 됩 니 다.
    begin
      for r in (select last_name from employees) loop
          dbms_output.put_line(r.last_name);
      end loop;
    end;
    /

    고급 디 스 플레이 커서 (매개 변수 가 있 는 커서)
    연습 1: 서로 다른 매개 변 수 를 입력 하여 커서 를 열 때 서로 다른 결과 집합 을 가 져 옵 니 다.
    declare
      cursor c1 (p_deptno number,p_job varchar2)
      is
      select empno,ename
      from emp
      where deptno=p_deptno
      and job=p_job;
    begin
      Dbms_output.put_line('first fetch cursor!');
      for r_c1 in c1(10,'MANAGER') loop   --open cursor                    !
        Dbms_output.put_line(r_c1.empno||' '||r_c1.ename);
      end loop;
    
      Dbms_output.put_line('second fetch cursor!');
      for r_c1 in c1(20,'MANAGER') loop
        Dbms_output.put_line(r_c1.empno||' '||r_c1.ename);
      end loop;
    
      Dbms_output.put_line('third fetch cursor!');
      for r_c1 in c1(30,'MANAGER') loop
        Dbms_output.put_line(r_c1.empno||' '||r_c1.ename);
      end loop;
    end;
    /

    연습: 각 부서 앞의 두 직원 의 정 보 를 얻 고 10 부서 앞의 두 사람의 정 보 를 얻 습 니 다.
    declare
      cursor c1 is select * from scott.emp 
                          where deptno=10;
    begin
      for r1 in c1 loop
        exit when c1%rowcount=3 or c1%notfound;
        dbms_output.put_line(r1.ename||' '||r1.deptno);
      end loop;
    end;
    /

    대체 변 수 를 사용 하여 지정 한 부서 의 두 사람의 정 보 를 가 져 옵 니 다.
    declare
      cursor c1 is select * from scott.emp 
                          where deptno=&p_deptno;
    begin
      for r1 in c1 loop
        exit when c1%rowcount=3 or c1%notfound;
        dbms_output.put_line(r1.ename||' '||r1.deptno);
      end loop;
    end;
    /

    대체 변수 대신 고급 커서 사용 하기
    declare
      cursor c1(p_deptno number) is select * from scott.emp 
                          where deptno=p_deptno;
    begin
      for r1 in c1(10) loop
        exit when c1%rowcount=3 or c1%notfound;
        dbms_output.put_line(r1.ename||' '||r1.deptno);
      end loop;
      for r1 in c1(20) loop
        exit when c1%rowcount=3 or c1%notfound;
        dbms_output.put_line(r1.ename||' '||r1.deptno);
      end loop;
      for r1 in c1(30) loop
        exit when c1%rowcount=3 or c1%notfound;
        dbms_output.put_line(r1.ename||' '||r1.deptno);
      end loop;
    end;
    /

    순환 플러그 인 을 사용 하여 위의 코드 를 간소화 하 다
    declare
      cursor c2 is select distinct deptno from scott.emp;
      cursor c1(p_deptno number) is 
                         select * from scott.emp 
                          where deptno=p_deptno;
    begin
      for r2 in c2 loop
        for r1 in c1(r2.deptno) loop
          exit when c1%rowcount=3 or c1%notfound;
          dbms_output.put_line(r1.ename||' '||r1.deptno);
        end loop;
      end loop;
    end;
    /

    연습 2: 각 부서 임금 2000 이하 직원 임금 10% 인상
    declare
      cursor c1 is select deptno from scott.dept;
      cursor c2 (p_deptno number,p_job varchar2)
      is
      select empno,ename,sal
      from emp
      where deptno=p_deptno
      and job=p_job
      for update of sal;    --      (  of sal   emp ,         ,         )
    begin
      for r_c1 in c1 loop 
        dbms_output.put_line(' '||c1%rowcount||'     c1' || '  '||r_c1.deptno||'       ');
        for r_c2 in c2(r_c1.deptno,'CLERK') loop  /*                           */
          if r_c2.sal<2000 then
                  update scott.emp set sal=sal*1.1
                  where current of c2;  /*   C2         */
               end if;
        end loop;
      end loop;
    end;
    /

    좋은 웹페이지 즐겨찾기