Oracle PL/SQL 커서: 암시적, 명시적, For 루프(예 포함)

⚡ 스마트 요약

커서 Oracle PL/SQL 커서는 SQL 문이 반환하는 행을 저장하는 컨텍스트 영역을 가리키는 포인터입니다. 커서에는 두 가지 종류가 있는데, DML 작업을 위해 자동으로 생성되는 암시적 커서와 프로그래머가 선언하고 제어하는 ​​명시적 커서가 있습니다.

  • 📍 컨텍스트 영역: 커서는 SQL 문과 해당 문이 반환한 활성 집합을 저장하는 컨텍스트 영역을 가리킵니다.
  • ⚙️ 암시적 커서: Oracle 모든 DML 문과 단일 행 SELECT INTO 문에 대해 암시적 커서를 자동으로 엽니다.
  • 명시적 커서: 프로그래머는 완벽한 제어를 위해 명시적인 커서를 선언하고, 열고, 가져오고, 닫습니다.
  • 🔎 커서 속성: %FOUND, %NOTFOUND, %ISOPEN 및 %ROWCOUNT는 가장 최근 작업의 상태를 보고합니다.
  • 🔁 커서 FOR 루프: FOR 루프는 수동 작업 없이 커서를 암묵적으로 열고, 가져오고, 닫습니다.
  • 🤖 AI 지원: GitHub Copilot과 같은 AI 비서는 커서 루프를 생성하고 닫히지 않은 커서를 표시합니다.

Oracle PL/SQL 커서 암시적, 명시적 및 FOR 루프

PL/SQL의 CURSOR란 무엇입니까?

커서는 컨텍스트 영역을 가리키는 포인터입니다. Oracle 처리를 위한 컨텍스트 영역을 생성합니다. SQL 이 영역에는 해당 진술에 대한 모든 정보가 포함되어 있습니다.

PL / SQL 프로그래머는 커서를 통해 컨텍스트 영역을 제어할 수 있습니다. 커서는 SQL 문에서 반환된 행들을 저장하며, 커서가 저장하는 행들의 집합을 활성 집합이라고 합니다. 이러한 커서에는 이름을 지정하여 코드의 다른 부분에서 참조할 수 있도록 할 수도 있습니다.

커서는 두 가지 유형이 있습니다.

  • 암시적 커서
  • 명시적 커서

암시적 커서

언제든지 DML 작업 데이터베이스에서 특정 작업이 발생하면 해당 작업의 영향을 받는 행을 저장하는 암시적 커서가 생성됩니다. 이러한 커서는 이름을 지정할 수 없으므로 코드의 다른 곳에서 제어하거나 참조할 수 없습니다. 커서 속성을 통해서만 가장 최근에 생성된 커서를 참조할 수 있습니다.

명시적 커서

프로그래머는 DML 작업을 실행하고 더 많은 제어 권한을 얻기 위해 명명된 컨텍스트 영역을 생성할 수 있습니다. 명시적인 커서는 선언 섹션에서 정의해야 합니다. PL/SQL 블록그리고 이 객체는 코드에서 사용해야 하는 SELECT 문을 위해 생성됩니다.

명시적 커서를 사용하는 단계는 다음과 같습니다.

  • 커서를 선언합니다: 커서를 선언한다는 것은 선언 부분에 정의된 SELECT 문에 대해 명명된 컨텍스트 영역을 하나 생성하는 것을 의미합니다. 이 컨텍스트 영역의 이름은 커서 이름과 동일합니다.
  • 커서 열기: 커서를 열면 PL/SQL은 해당 커서에 필요한 메모리를 할당합니다. 이렇게 하면 커서가 레코드를 가져올 준비가 됩니다.
  • 커서에서 데이터를 가져오는 중: 이 과정에서 SELECT 문이 실행되고 가져온 행들이 할당된 메모리에 저장됩니다. 이러한 행들을 활성 세트라고 합니다. 커서에서 데이터를 가져오는 것은 레코드 수준의 작업이므로 레코드 단위로 데이터에 접근할 수 있습니다. 각 페치 문은 하나의 활성 세트를 가져오고 해당 레코드의 정보를 저장합니다. 이 문은 레코드를 가져와 INTO 절의 변수에 할당하는 SELECT 문과 동일하지만 예외를 발생시키지 않습니다. 예외.
  • 커서 닫기: 모든 레코드를 가져온 후에는 커서를 닫아 해당 컨텍스트 영역에 할당된 메모리를 해제해야 합니다.

통사론

DECLARE
CURSOR <cursor_name> IS <SELECT statement>;
<cursor_variable declaration>;
BEGIN
OPEN <cursor_name>;
FETCH <cursor_name> INTO <cursor_variable>;
.
.
CLOSE <cursor_name>;
END;

위 구문에서 선언 부분에는 커서와 가져온 데이터가 할당될 커서 변수의 선언이 포함됩니다. 커서는 커서 선언 부분에 지정된 SELECT 문을 실행하기 위해 생성됩니다. 실행 부분에서는 선언된 커서가 열리고, 데이터가 가져와지고, 닫힙니다.

커서 속성

암시적 커서와 명시적 커서 모두 접근 가능한 특정 속성을 가지고 있습니다. 이러한 속성들은 커서 작업에 대한 더 자세한 정보를 제공합니다. 아래는 다양한 커서 속성과 그 사용법입니다.

커서 속성 기술설명
%녹이다 가장 최근의 레코드 가져오기 작업이 성공적으로 완료되면 TRUE를 반환하고, 그렇지 않으면 FALSE를 반환합니다.
% NOTFOUND %FOUND와 반대로 작동합니다. 가장 최근의 조회 작업에서 레코드를 전혀 가져오지 못한 경우 TRUE를 반환합니다.
% ISOPEN 주어진 커서가 이미 열려 있으면 TRUE를, 그렇지 않으면 FALSE를 반환하는 부울 결과입니다.
% ROWCOUNT % 이 함수는 작업으로 인해 영향을 받거나 가져온 레코드의 실제 개수를 나타내는 숫자 값을 반환합니다.

명시적 커서 예시: 이 예제에서는 명시적 커서를 선언, 열기, 가져오기 및 닫기하는 방법을 살펴보겠습니다. 커서를 사용하여 emp 테이블에서 모든 직원 이름을 가져올 것입니다. 또한 커서 속성을 사용하여 루프가 커서에서 모든 레코드를 가져오도록 설정할 것입니다.

아래 스크린샷은 명시적 커서 예제와 그 출력 결과를 보여줍니다. Oracle.

명시적 커서를 사용하여 emp 테이블에서 직원 이름을 가져오는 예제 Oracle PL / SQL

DECLARE
CURSOR guru99_det IS SELECT emp_name FROM emp;
lv_emp_name emp.emp_name%type;
BEGIN
OPEN guru99_det;
LOOP
FETCH guru99_det INTO lv_emp_name;
IF guru99_det%NOTFOUND
THEN
EXIT;
END IF;
Dbms_output.put_line('Employee Fetched:'||lv_emp_name);
END LOOP;
Dbms_output.put_line('Total rows fetched is'||guru99_det%ROWCOUNT);
CLOSE guru99_det;
END;
/

산출

Employee Fetched:BBB
Employee Fetched:XXX
Employee Fetched:YYY
Total rows fetched is 3

Code 설명

  • Code 2행: 'SELECT emp_name FROM emp' 문에 대한 커서 guru99_det를 선언합니다.
  • Code 3행: lv_emp_name 변수를 다음과 같이 선언합니다. %유형 emp.emp_name에 고정되어 있습니다.
  • Code 5행: 커서 guru99_det을 엽니다.
  • Code 6행: emp 테이블의 모든 레코드를 가져오는 기본 반복문을 설정합니다.
  • Code 7행: guru99_det 데이터를 가져와서 해당 값을 lv_emp_name에 할당합니다.
  • Code 8행: 커서 속성 %NOTFOUND를 사용하여 커서에 있는 모든 레코드가 가져와졌는지 확인합니다. 모든 레코드가 가져와졌다면 TRUE를 반환하고 루프를 종료합니다. 그렇지 않으면 커서에서 데이터를 계속 가져와 출력합니다.
  • Code 10행: 루프 문의 EXIT 조건입니다.
  • Code 12행: 가져온 직원 이름을 인쇄합니다.
  • Code 14행: 커서 속성인 %ROWCOUNT를 사용하여 커서가 가져온 총 레코드 수를 찾습니다.
  • Code 15행: 루프를 종료하면 커서가 닫히고 할당된 메모리가 해제됩니다.

FOR 루프 커서 문

커서 FOR 루프 커서를 사용하여 작업할 수 있습니다. FOR 루프 문에서 범위 제한 대신 커서 이름을 지정하면 루프가 커서의 첫 번째 레코드부터 마지막 ​​레코드까지 반복합니다. 커서 변수 지정, 커서 열기, 데이터 가져오기 및 닫기는 모두 FOR 루프에 의해 암묵적으로 처리됩니다.

통사론

DECLARE
CURSOR <cursor_name> IS <SELECT statement>;
BEGIN
FOR I IN <cursor_name>
LOOP
.
.
END LOOP;
END;

위 구문에서 선언 부분은 커서를 선언합니다. 이 커서는 커서 선언 부분에 지정된 SELECT 문을 실행하기 위해 생성됩니다. 실행 부분에서는 선언된 커서가 FOR 루프 내에 설정되고, 루프 변수 'I'는 이 경우 커서 변수 역할을 합니다.

Oracle 커서를 이용한 반복문 예시: 이 예제에서는 커서-FOR 루프를 사용하여 emp 테이블에서 모든 직원 이름을 가져옵니다.

DECLARE
CURSOR guru99_det IS SELECT emp_name FROM emp;
BEGIN
FOR lv_emp_name IN guru99_det
LOOP
Dbms_output.put_line('Employee Fetched:'||lv_emp_name.emp_name);
END LOOP;
END;
/

산출

Employee Fetched:BBB
Employee Fetched:XXX
Employee Fetched:YYY

Code 설명

  • Code 2행: 'SELECT emp_name FROM emp' 문에 대한 커서 guru99_det를 선언합니다.
  • Code 4행: 커서에 대한 FOR 루프를 루프 변수 lv_emp_name을 사용하여 구성합니다.
  • Code 6행: 루프가 반복될 때마다 직원 이름을 인쇄합니다.
  • Code 7행: 루프를 종료합니다(END LOOP).

참고 : 커서-FOR 루프에서는 커서의 속성을 사용할 수 없습니다. 커서를 열고, 가져오고, 닫는 작업이 FOR 루프에 의해 암묵적으로 수행되기 때문입니다.

자주 묻는 질문

참조 커서(ref cursor)는 쿼리 결과 집합을 가리키는 포인터입니다. 정적 커서와 달리, 참조 커서는 실행 시간에 여러 쿼리를 열고 PL/SQL 블록 간 또는 클라이언트 프로그램으로 결과를 전달할 수 있습니다.

일반 커서는 FETCH 호출마다 한 행씩 가져오므로 컨텍스트 전환이 많이 발생합니다. 대량 수집 한 번의 데이터 가져오기로 여러 행을 컬렉션에 로드하여 대규모 결과 집합에서 오버헤드를 크게 줄입니다.

예. CURSOR c(dept NUMBER) IS SELECT …와 같이 매개변수화된 커서를 선언한 다음 OPEN c(10)에 값을 전달합니다. 매개변수를 사용하면 다른 필터 값으로 하나의 커서 정의를 재사용할 수 있습니다.

FOR UPDATE는 커서가 선택한 행을 잠가 다른 사용자가 변경할 수 없도록 합니다. WHERE CURRENT OF는 WHERE 조건을 반복하지 않고 방금 가져온 행을 정확히 업데이트하거나 삭제합니다.

열린 커서는 메모리를 예약해 두고 OPEN_CURSORS 제한에 포함됩니다. 많은 커서를 열어둔 채로 방치하면 결국 ORA-01000 오류(열린 커서 최대 개수 초과)가 발생하므로, 사용 후에는 반드시 명시적인 커서를 닫아야 합니다.

각 FETCH 문은 PL/SQL 엔진과 SQL 엔진 사이를 전환합니다. 이러한 컨텍스트 전환이 수천 번 발생하므로, 일반적으로 단일 집합 기반 SQL 문이나 BULK COLLECT 문을 사용하는 것이 동일한 행을 훨씬 빠르게 처리합니다.

예. GitHub 부조종사 주석에서 명시적인 OPEN, FETCH, CLOSE 루프 또는 커서 FOR 루프를 작성하고, %NOTFOUND 종료 검사를 추가하며, 속성 이름을 제안합니다. 단, 먼저 논리를 검토해야 합니다.

AI 어시스턴트는 행 단위 커서 루프가 집합 기반 SQL 또는 대량 수집(BULK COLLECT)으로 이어질 가능성을 표시하고, 닫히지 않은 커서를 찾아내며, %속성 동작 방식을 설명합니다. 이러한 머신러닝 기반 검토를 통해 코드가 프로덕션 환경에 배포되기 전에 성능을 향상시킬 수 있습니다.

이 게시물을 요약하면 다음과 같습니다.