본문 바로가기

DB/Oracle

[Oracle] 커서(Cursor)

SET SERVEROUTPUT ON

CREATE OR REPLACE PROCEDURE info_Hiredate
(p_year IN CHAR := 0)
IS
      l_emp employees%ROWTYPE;

BEGIN

     SELECT employee_id, last_name, salary
     INTO l_emp.employee_id, l_emp.last_name, l_emp.salary
     FROM employees
     WHERE TO_CHAR(hire_date, 'YYYY') = p_year;
     
     DBMS_OUTPUT.PUT_LINE(l_emp.employee_id || '' || l_emp.last_name || '' || l_emp.salary);

END ;

EXEC info_Hiredate('1994')

 

ORA-01422: 실제 인출은 요구된 것보다 많은 수의 행을 추출합니다.

-> 로컬 변수를 선언하여 INTO절에서 처리할 수 있는 행의 수는 하나의 행만이 가능합니다.  

    즉 여러 행일 때는 위와 같은 방법으로 처리할 수 없다는 뜻 

-> 커서(Cursor)를 이용하여 질의 수행 결과 반환되는 여러 행을 처리

 

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

 

커서란 어떤 위치를 가리키는 속성을 가짐

Oracle에서의 커서는 질의의 결과 얻어진 여러 행이 저장된 메모리 상의 위치를 나타냄

즉, PL/SQL 에 내장된 일종의 포인트이며, 결과  SET의 행들을 하나씩 얻어오는 작업에 이용됨

 

명시적 커서의 구문

 

DECLARE

-- 커서의 선언

    CURSOR 커서이름 IS SELECT 구문;

 

BEGIN

-- 커서 열기

    OPEN 커서이름;

 

-- 커서로부터 데이터 읽기

    FETCH 커서이름 INTO 로컬변수;

 

-- 커서 닫기

    CLOSE 커서이름;

 

END;

 

 

ORA-01422: 실제 인출은 요구된 것보다 많은 수의 행을 추출합니다.

에러뜬 쿼리, 커서를 이용하여 작성하기

 

SET SERVEROUTPUT ON

CREATE OR REPLACE PROCEDURE info_Hiredate
        (p_year IN CHAR := 0)
IS
        l_emp employees%ROWTYPE;

-- 커서의 선언

-- CURSOR 커서이름 IS SELECT 구문;

CURSOR emp_cur IS
       SELECT employee_id, last_name, salary
       FROM employees
       WHERE TO_CHAR(hire_date, 'YYYY') = p_year;

BEGIN

      -- 커서 열기

      -- OPEN 커서이름;

      OPEN emp_cur;



      -- 커서로부터 데이터 읽기

      -- FETCH 커서이름 INTO 지역변수;

       FETCH emp_cur INTO l_emp.employee_id, l_emp.last_name, l_emp.salary;

       DBMS_OUTPUT.PUT_LINE(l_emp.employee_id || '' || l_emp.last_name || '' || l_emp.salary);

       -- 커서 닫기

       -- CLOSE cursor_name;

       CLOSE emp_cur;

END info_Hiredate;

EXEC info_Hiredate('1994')

 

에러 없이 정상적으로 결과가 나옴 But 반환되는 결과는 일부에 불과함

-> 반복문 LOOP를 사용해서 여러번의 FETCH로 모든 레코드를 얻도록 해야함

 

-- 커서로부터 데이터 읽기

      -- FETCH 커서이름 INTO 지역변수;

     

 LOOP
                  FETCH emp_cur INTO l_emp.employee_id, l_emp.last_name, l_emp.salary;
                  EXIT WHEN emp_cur%NOTFOUND;
                  
                  DBMS_OUTPUT.PUT_LINE(l_emp.employee_id || '' || l_emp.last_name || '' || l_emp.salary);

       END LOOP;

 

 

-- %FOUND  : PL/SQL 코드가 마지막으로 얻은 커서의 결과 SET에 레코드가 있다면 참입니다.

-- %NOTFOUND : %FOUND 연산자와 반대의 의미입니다.

-- %ROWCOUNT : 커서에서 얻은 레코드의 수를 반환합니다.

-- %ISOPEN : 커서가 열렸고, 아직 닫히지 않은 상태라면 참입니다.