반응형

오라클 데이터베이스에서 커서(Cursor)는 SQL 문 실행 결과를 메모리에서 저장하는 일종의 컨테이너입니다. 커서를 사용하면 여러 행을 포함하는 쿼리 결과를 순차적으로 처리할 수 있습니다. 특히, PL/SQL 블록에서 프로그래밍적으로 데이터를 조작할 때 유용합니다.

이 글에서는 커서의 기본 개념부터 사용법, 예제, 그리고 실무 활용까지 다양한 내용을 자세히 다룹니다.


1. 커서란?

커서(Cursor)는 SQL 실행 결과를 참조하는 포인터로, PL/SQL 블록에서 SQL 문 실행 결과를 행 단위로 처리할 때 사용됩니다.

1.1. 커서의 종류

오라클에서 커서는 다음과 같이 두 가지로 나뉩니다:

  1. 암시적 커서 (Implicit Cursor)

    • Oracle Database가 SQL 문을 실행할 때 자동으로 생성됩니다.
    • 예: INSERT, UPDATE, DELETE 등 DML 문 실행 시 사용.
  2. 명시적 커서 (Explicit Cursor)

    • 프로그래머가 직접 선언하고 제어하는 커서입니다.
    • 주로 SELECT 문으로 다중 행을 처리할 때 사용됩니다.

2. 암시적 커서

2.1. 개념

  • 오라클은 SQL 문 실행 후 결과를 암시적으로 관리합니다.
  • 실행 결과는 SQL% 속성을 사용하여 참조할 수 있습니다.

2.2. 주요 속성

암시적 커서의 속성은 다음과 같습니다:

  • SQL%FOUND: 마지막 SQL 문이 하나 이상의 행에 영향을 미쳤다면 TRUE.
  • SQL%NOTFOUND: 마지막 SQL 문이 영향을 미치지 않았다면 TRUE.
  • SQL%ROWCOUNT: 마지막 SQL 문으로 영향을 받은 행 수.
  • SQL%ISOPEN: 커서가 열려 있는지 확인 (항상 FALSE, 암시적 커서는 자동으로 닫히기 때문).

2.3. 예제

DECLARE
    v_rows NUMBER;
BEGIN
    UPDATE employees
    SET salary = salary * 1.1
    WHERE department_id = 10;

    IF SQL%FOUND THEN
        v_rows := SQL%ROWCOUNT;
        DBMS_OUTPUT.PUT_LINE('총 ' || v_rows || '개 행이 업데이트되었습니다.');
    ELSE
        DBMS_OUTPUT.PUT_LINE('업데이트된 행이 없습니다.');
    END IF;
END;
/

3. 명시적 커서

3.1. 개념

  • 명시적 커서는 SELECT 문으로 반환된 다중 행을 제어하기 위해 사용됩니다.
  • 프로그래머가 커서를 선언, 열기, 가져오기, 닫기 과정을 명시적으로 처리해야 합니다.

3.2. 주요 단계

명시적 커서를 사용하는 과정은 다음과 같습니다:

  1. 커서 선언

    • SELECT 문을 기반으로 커서를 정의합니다.
      CURSOR cursor_name IS SELECT column1, column2 FROM table_name WHERE condition;
  2. 커서 열기

    • OPEN 문으로 커서를 실행합니다.
      OPEN cursor_name;
  3. 커서에서 데이터 가져오기

    • FETCH 문으로 한 행씩 데이터를 가져옵니다.
      FETCH cursor_name INTO variable1, variable2;
  4. 커서 닫기

    • CLOSE 문으로 커서를 닫습니다.
      CLOSE cursor_name;

4. 명시적 커서 예제

4.1. 기본 예제

DECLARE
    CURSOR emp_cursor IS
        SELECT first_name, last_name, salary
        FROM employees
        WHERE department_id = 10;

    v_first_name employees.first_name%TYPE;
    v_last_name employees.last_name%TYPE;
    v_salary employees.salary%TYPE;
BEGIN
    OPEN emp_cursor;

    LOOP
        FETCH emp_cursor INTO v_first_name, v_last_name, v_salary;

        EXIT WHEN emp_cursor%NOTFOUND;

        DBMS_OUTPUT.PUT_LINE('이름: ' || v_first_name || ' ' || v_last_name || ', 급여: ' || v_salary);
    END LOOP;

    CLOSE emp_cursor;
END;
/

4.2. 매개변수가 있는 커서

DECLARE
    CURSOR emp_cursor(dept_id NUMBER) IS
        SELECT first_name, last_name
        FROM employees
        WHERE department_id = dept_id;

    v_first_name employees.first_name%TYPE;
    v_last_name employees.last_name%TYPE;
BEGIN
    OPEN emp_cursor(20);

    LOOP
        FETCH emp_cursor INTO v_first_name, v_last_name;

        EXIT WHEN emp_cursor%NOTFOUND;

        DBMS_OUTPUT.PUT_LINE('이름: ' || v_first_name || ' ' || v_last_name);
    END LOOP;

    CLOSE emp_cursor;
END;
/

5. REF CURSOR

REF CURSOR는 명시적 커서의 동적 버전으로, 런타임에 커서 쿼리를 동적으로 정의할 수 있습니다.

5.1. REF CURSOR 선언

DECLARE
    TYPE ref_cursor IS REF CURSOR;
    v_cursor ref_cursor;
    v_first_name employees.first_name%TYPE;
    v_last_name employees.last_name%TYPE;
BEGIN
    OPEN v_cursor FOR
        SELECT first_name, last_name
        FROM employees
        WHERE department_id = 30;

    LOOP
        FETCH v_cursor INTO v_first_name, v_last_name;

        EXIT WHEN v_cursor%NOTFOUND;

        DBMS_OUTPUT.PUT_LINE('이름: ' || v_first_name || ' ' || v_last_name);
    END LOOP;

    CLOSE v_cursor;
END;
/

6. 커서 속성

커서 속성은 커서의 상태를 확인하는 데 사용됩니다.

  • %FOUND: 데이터를 가져온 경우 TRUE.
  • %NOTFOUND: 데이터를 가져오지 못한 경우 TRUE.
  • %ROWCOUNT: FETCH된 행의 개수.
  • %ISOPEN: 커서가 열려 있으면 TRUE.

예제

DECLARE
    CURSOR emp_cursor IS
        SELECT first_name FROM employees WHERE department_id = 10;

    v_name employees.first_name%TYPE;
BEGIN
    OPEN emp_cursor;

    FETCH emp_cursor INTO v_name;

    IF emp_cursor%FOUND THEN
        DBMS_OUTPUT.PUT_LINE('첫 번째 이름: ' || v_name);
    END IF;

    CLOSE emp_cursor;

    IF NOT emp_cursor%ISOPEN THEN
        DBMS_OUTPUT.PUT_LINE('커서가 닫혔습니다.');
    END IF;
END;
/

7. 커서 사용 시 주의사항

  1. 메모리 관리

    • 커서를 열면 메모리를 차지합니다. 사용 후 반드시 닫아야 합니다.
    • 닫지 않으면 ORA-01000: maximum open cursors exceeded 오류가 발생할 수 있습니다.
  2. 효율적인 사용

    • 다중 행 쿼리를 처리할 때만 사용하세요. 단일 행은 암시적 커서로 충분합니다.
    • 불필요한 커서 사용은 성능에 부정적인 영향을 미칠 수 있습니다.
  3. 중첩 커서

    • 커서를 중첩하여 사용하면 코드 복잡도가 증가합니다. 반드시 필요한 경우에만 사용하세요.

8. 결론

오라클 커서는 SQL 쿼리 결과를 다중 행으로 처리해야 할 때 매우 유용한 도구입니다. 암시적 커서는 단순한 DML 작업에 적합하고, 명시적 커서는 복잡한 데이터 처리가 필요한 경우에 적합합니다. 또한, REF CURSOR를 사용하면 동적 쿼리를 처리할 수 있습니다.

커서를 올바르게 사용하면 애플리케이션 성능과 유지보수성을 크게 향상시킬 수 있습니다. 하지만 사용 후 반드시 닫는 등 메모리 관리를 철저히 해야 합니다. 다양한 예제를 통해 커서의 기능을 익히고, 프로젝트에 적절히 활용해 보세요!

반응형

+ Recent posts