일반 루프 대신 명시 적 커서를 사용하는 이유는 무엇입니까?


12

나는 1 년 동안 (Oracle db 용) 기본 웹 응용 프로그램을 작성해 왔으며 함수가 매우 간단하기 때문에 대부분의 사람들은 정기적 인 FOR 루프를 사용하여 데이터를 얻습니다.

for i in (select * from STUDENTS) loop
      htp.prn(i.student_last_name || ', ' || i.student_first_name || ' ' || i.student_dob);
end loop;

그러나 커서는 일을하는 '올바른'방법 인 것 같습니다. 커서가 무엇인지, 커서를 반복하는 다른 방법에 대한 많은 정보를 찾을 수 있지만 일반 FOR 루프보다 커서를 사용해야하는 확실한 이유를 찾을 수 없습니다. 절차의 필요에 따라 결정됩니까? 내가 알아야 할 고유의 장점이 있습니까?


이 유형은 FOR커서를 사용하는 또 다른 방법입니다. docs.oracle.com/cd/E11882_01/appdev.112/e10472 / ... 문서를 참조하십시오. 어쨌든 htp.prn ()은 무엇입니까?
dezso

그것은 우리의 출력 함수 중 하나입니다. 그렇다면 어떤 방법을 선호합니까?
ini

이런 종류의 것들에 대해서는 FOR루프가 훨씬 더 읽기 쉽습니다. 나는 단지 앞으로가 아니라 뒤로 물러서야하는 경우에만 '실제'커서를 사용하는 경향이 있습니다. 대신 테이블 함수를 상상할 수 있기 때문에 다른 질문을했습니다 htp.prn().
dezso

두 가지 형태의 커서는 특히 DML 문과 관련된 순수 SQL 솔루션보다 성능이 떨어진다는 점을 언급 할 가치가 있습니다.
David Aldridge

답변:


7

커서는 명시 적이거나 암시적일 수 있으며 FOR 루프에서 두 유형을 모두 사용할 수 있습니다. 귀하의 질문에는 실제로 두 가지 측면이 있습니다.

  1. 암시 적 커서 FOR 루프에 명시 적 커서 FOR 루프를 사용하는 이유는 무엇입니까?

    • 조회를 재사용 할 때 명시 적 커서 FOR 루프를 사용하십시오. 그렇지 않으면 내재적 커서가 선호됩니다.
  2. 명시 적 FETCH가없는 FOR 루프 대신 FETCH가있는 루프를 사용하는 이유는 무엇입니까?

    • 대량 수집이 필요하거나 동적 SQL이 필요한 경우 루프 내에서 FETCH를 사용하십시오.

다음은 설명서에서 유용한 정보입니다.

루프에 대한 암시 적 커서의 예

BEGIN
   FOR vItems IN (
      SELECT last_name
      FROM employees
      WHERE manager_id > 120
      ORDER BY last_name
   ) 
   LOOP
      DBMS_OUTPUT.PUT_LINE ('Name = ' || vItems.last_name);
   END LOOP;
END;
/

루프에 대한 명시 적 커서의 예

DECLARE
   CURSOR c1 IS
      SELECT last_name
      FROM employees
      WHERE manager_id > 120
      ORDER BY last_name;
BEGIN
   FOR vItems IN c1 LOOP
      DBMS_OUTPUT.PUT_LINE ('Name = ' || vItems.last_name);
   END LOOP;
END;
/

암시 적 커서

암시 적 커서는 PL / SQL에 의해 구성되고 관리되는 세션 커서입니다. PL / SQL은 SELECT 또는 DML 문을 실행할 때마다 암시 적 커서를 엽니 다. 암시 적 커서는 제어 할 수 없지만 해당 속성에서 정보를 얻을 수 있습니다.

연관된 명령문이 실행 된 후 내재 된 커서가 닫힙니다. 그러나 다른 SELECT 또는 DML 문이 실행될 때까지 속성 값을 계속 사용할 수 있습니다.

내재적 커서 속성은 SQL % ISOPEN, SQL % FOUND, SQL % NOTFOUND, SQL % ROWCOUNT, SQL % BULK_ROWCOUNT, SQL % BULK_EXCEPTIONS입니다.

명시 적 커서

명시 적 커서는 구성하고 관리하는 세션 커서입니다. 명시 적 커서를 선언하고 정의하여 이름을 지정하고이를 쿼리와 연관시켜야합니다 (일반적으로 쿼리는 여러 행을 리턴 함). 그런 다음 다음 방법 중 하나로 쿼리 결과 세트를 처리 할 수 ​​있습니다.

OPEN 문을 사용하여 명시 적 커서를 열고, FETCH 문을 사용하여 결과 세트에서 행을 페치 한 후, CLOSE 문을 사용하여 명시 적 커서를 닫으십시오.

커서 FOR LOOP 문에 명시 적 커서를 사용하십시오 ( "커서 FOR LOOP 문을 사용한 쿼리 결과 세트 처리"참조).

명시 적 커서에 값을 지정하거나 표현식에 사용하거나 공식 서브 프로그램 매개 변수 또는 호스트 변수로 사용할 수 없습니다. 커서 변수로 이러한 작업을 수행 할 수 있습니다 ( "커서 변수"참조).

암시 적 커서와 달리 이름으로 명시 적 커서 또는 커서 변수를 참조 할 수 있습니다. 따라서 명시 적 커서 또는 커서 변수를 명명 된 커서라고합니다.

커서 FOR LOOP 문

커서 FOR LOOP 문을 사용하면 SELECT 문을 실행 한 후 결과 세트의 행을 즉시 반복 할 수 있습니다. 이 명령문은 내재적 커서 또는 명시 적 커서를 사용할 수 있습니다.


1
암시 적 커서는 10g부터 한 번에 100 개의 행을 가져옵니다.
David Aldridge

16

게시 한 코드는 커서를 사용하고 있습니다. 암시 적 커서 루프를 사용하고 있습니다.

명시 적 커서 루프를 사용하면 (예 : 선언 섹션에서 CURSOR 변수 선언) 더 깨끗한 코드 또는 더 나은 성능을 생성하는 경우가 있습니다.

  1. 뷰로 리팩토링 할 수없는 더 복잡한 쿼리가있는 경우 루프가 반복되는 경우 코드를보다 쉽게 ​​읽을 수 있습니다. student_cursor많은 논리를 포함하는 30 행 SQL 문을 포함시키는 것이 아닙니다. 예를 들어, 졸업 허가를 받았으며 학업 기록이있는 테이블, 학위 프로그램 요구 사항, 학업 정보가있는 테이블, 연체 된 도서관 도서에 대한 정보가있는 테이블, 미결제 수수료, 관리 재정의 등에 대한 정보가 포함 된 테이블은 코드를 리팩터링하여이 쿼리가 사용자에게 목록을 표시하는 데 관련된 코드 중간에 갇히지 않도록하는 것이 좋습니다. 이 모든 논리를 캡슐화하는 뷰를 만드는 것이 포함될 수 있습니다. 또는 현재 PL / SQL 블록의 일부로 또는 일부 상위 레벨 PL / SQL 블록으로 선언 된 명시 적 커서를 작성해야 할 수도 있습니다 (예 : 재사용 가능하도록 패키지에 선언 된 커서). 또는 캡슐화 및 재사용을 위해 다른 작업을 수행해야 할 수도 있습니다 (예 : 대신 파이프 라인 테이블 함수 작성).
  2. PL / SQL에서 대량 작업을 사용하려면 일반적으로 명시 적 커서를 사용하려고합니다. 다음은 명시 적 커서와 암시 적 커서성능 차이에 대해 설명하는 StackOverflow 스레드입니다 . 당신이하고있는 모든 호출하는 경우 htp.prn하는 일을 BULK COLLECT당신에게 아무것도 구입하지 않습니다 아마. 그러나 다른 경우에는 성능이 크게 향상 될 수 있습니다.

2

많은 개발자들이 오래된 습관에서 암시 적 커서 대신 명시 적 커서를 사용하고 있음을 알았습니다. 이것은 Oracle 버전 7로 돌아 가기 때문에 항상 더 효율적인 방법이었습니다. 요즘에는 일반적으로 다른 방법이 있습니다. 특히 최적화 프로그램을 사용하면 필요한 경우 루프에 대한 암시 적 커서를 대량 수집으로 다시 쓸 수 있습니다.


0

최근에 암시 적 FOR 루프에서 명시 적 커서로 많은 쿼리를 다시 작성해야했습니다. 그 이유는 쿼리가 링크를 통해 외부 데이터베이스에서 데이터를 가져 왔으며이 데이터베이스는 로컬 데이터베이스와 다른 인코딩을 사용했기 때문입니다. 암시 적 커서에서 로컬로 정의 된 레코드 유형으로 데이터를 전송할 때 (일부 특정 행에서만) 심각한 간헐적 오류가 발생했습니다. 우리 DBA는 이것을 우리에게 설명했지만, 우리는 이것의 바닥에 도달 할 수 없었을 것입니다. 이것은보고 된 Oracle의 버그 인 것 같습니다.

명시 적 커서를 사용하여 모든 것을 다시 작성하도록 권고 받았으며 오류는 사라졌습니다.

암시 적보다 명시 적을 사용하려는 주된 이유는 아니지만 참고할 가치가 있습니다.

편집 : Oracle 12c.


이 글을 읽는 사람들이 증상에 대해 더 많이 알 수 있도록 버그 및 / 또는 메모 번호를 추가 할 수 있습니까?
레이 리펠

죄송합니다. DBA 중 하나가 버그보고를했는데 해당 정보에 액세스 할 수 없습니다.
Robotron
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.