PL/SQL에서 ORA-06511: PL/SQL: cursor already open 오류는 커서가 이미 열려있는 상태에서 다시 열려고 할 때 발생합니다. 이 오류는 주로 커서를 열고 닫는 순서를 잘못 처리했을 때 나타나요.
ORA-06511 오류 원인
PL/SQL의 명시적 커서는 OPEN, FETCH, CLOSE 순으로 사용해야 합니다. 하지만 이미 열려있는 커서를 다시 열려고 시도하면 ORA-06511 오류가 발생합니다. 이 문제는 커서를 닫지 않거나 닫기 전에 다시 열려고 할 때 발생한답니다.
다음 코드는 ORA-06511 오류를 발생시키는 예제입니다.
오류가 발생하는 예제 코드
DECLARE
CURSOR emp_cursor IS
SELECT * FROM emp;
v_emp emp%ROWTYPE;
BEGIN
OPEN emp_cursor; -- 커서를 한 번 엽니다.
LOOP
FETCH emp_cursor INTO v_emp; -- 데이터를 가져옵니다.
EXIT WHEN emp_cursor%NOTFOUND;
--DBMS_OUTPUT.PUT_LINE(v_emp.ename);
END LOOP;
-- 커서를 닫지 않고 다시 열려고 합니다.
OPEN emp_cursor; -- 오류 발생: 이미 커서가 열려있습니다.
END;
/
DECLARE
ERROR at line 1:
ORA-06511: PL/SQL: cursor already open
ORA-06512: at line 3
ORA-06512: at line 14
위 코드에서 emp_cursor를 첫 번째 루프에서 열고 닫지 않은 상태로 두 번째 OPEN을 시도했기 때문에 오류가 발생합니다. PL/SQL은 동일한 커서를 다시 열기 전에 반드시 닫아야 해요.
ORA-06511 오류를 해결하려면 커서를 다시 열기 전에 반드시 닫아야 합니다. 다음과 같이 올바른 커서 사용 순서와 수정된 코드를 안내해 드릴게요.
커서를 올바르게 닫기 (CLOSE)
커서를 닫기 위해 CLOSE 명령어를 사용합니다. 커서를 닫으면 메모리가 해제되고, 이후에 다시 열어도 오류가 발생하지 않습니다. 수정된 코드는 다음과 같습니다.
DECLARE
CURSOR emp_cursor IS
SELECT * FROM emp;
v_emp emp%ROWTYPE;
BEGIN
OPEN emp_cursor; -- 커서를 한 번 엽니다.
LOOP
FETCH emp_cursor INTO v_emp; -- 데이터를 가져옵니다.
EXIT WHEN emp_cursor%NOTFOUND;
--DBMS_OUTPUT.PUT_LINE(v_emp.ename);
END LOOP;
CLOSE emp_cursor;
-- 커서를 닫지 않고 다시 열려고 합니다.
OPEN emp_cursor; -- 오류 발생: 이미 커서가 열려있습니다.
CLOSE emp_cursor;
END;
/
PL/SQL procedure successfully completed.
이 코드는 커서를 두 번 열고 두 번 닫는 구조로, 오류 없이 정상적으로 작동합니다.
커서를 반복적으로 열고 닫지 않기
가능하다면, 커서를 반복적으로 열고 닫는 것을 피하는 것이 좋습니다. 한 번 열어놓은 커서에서 데이터를 처리한 후, 필요하면 다른 방식으로 데이터를 다시 가져오도록 설계하세요. 다음은 커서를 한 번만 열고 데이터를 처리하는 예제입니다.
DECLARE
CURSOR emp_cursor IS
SELECT * FROM emp;
v_emp emp%ROWTYPE;
BEGIN
OPEN emp_cursor; -- 커서를 한 번만 엽니다.
LOOP
FETCH emp_cursor INTO v_emp;
EXIT WHEN emp_cursor%NOTFOUND;
--DBMS_OUTPUT.PUT_LINE(v_emp.ename);
END LOOP;
CLOSE emp_cursor; -- 작업이 끝나면 커서를 닫습니다.
END;
/
PL/SQL procedure successfully completed.
암시적 커서를 사용하는 방식 고려
명시적 커서를 사용하는 대신 암시적 커서를 활용할 수도 있습니다. 암시적 커서는 SELECT INTO 구문으로 데이터를 직접 가져올 때 사용되며, 자동으로 열리고 닫히므로 명시적인 OPEN이나 CLOSE 명령어가 필요하지 않습니다. 단, 데이터가 많을 경우 암시적 커서는 적합하지 않을 수 있습니다.
BEGIN
FOR i IN (SELECT ename FROM emp) LOOP
--DBMS_OUTPUT.PUT_LINE(i.ename);
NULL;
END LOOP;
END;
/
PL/SQL procedure successfully completed.커서 관리 시 유의할 점
- 커서를 항상 닫기:
CLOSE명령어를 누락하면 메모리 누수나 예기치 않은 오류가 발생할 수 있습니다. - 커서를 필요 이상으로 반복적으로 열지 않기: 커서를 여러 번 열고 닫는 것은 성능에 영향을 미칠 수 있습니다. 한 번만 열고 데이터를 처리하는 방식이 좋아요.
- 암시적 커서 활용 검토: 간단한 작업에서는 암시적 커서가 더 효율적일 수 있습니다.
요약
ORA-06511: PL/SQL: cursor already open 오류는 명시적 커서를 사용하는 경우 커서를 제대로 닫지 않을 때 발생합니다. 이를 해결하기 위해서는 커서를 닫는 명령어를 추가하거나 커서를 한 번만 열고 데이터를 처리하도록 코드를 작성하세요.
