Oracle PL/SQL BULK COLLECT: FORALL 예

⚡ 스마트 요약

대량 수집 Oracle PL/SQL은 한 번에 여러 행을 컬렉션으로 가져오는 반면, FORALL은 대량의 DML 작업을 데이터베이스로 다시 푸시합니다. 둘 다 SQL 엔진과 PL/SQL 엔진 간의 컨텍스트 전환을 줄여 성능을 향상시킵니다.

  • 📦 대량 수거: 한 번에 여러 행을 가져와 컬렉션 변수에 저장하므로, 느린 행별 가져오기 방식을 대체합니다.
  • 🔁 모두를 위한: 단일 컨텍스트 전환으로 전체 컬렉션에 대해 하나의 INSERT, UPDATE 또는 DELETE 작업을 실행합니다.
  • 📏 제한 조항: 대용량 테이블에서 세션 메모리를 보호하기 위해 BULK COLLECT 페치 로드당 행 수를 제한합니다.
  • 📊 대량 수집 속성: %BULK_ROWCOUNT(n) 속성은 n번째 FORALL DML 문이 영향을 미친 행 수를 보고합니다.
  • ⚙️ 수집 필요 자료: INTO 절은 중첩 테이블이나 연관 배열과 같은 컬렉션 유형을 대상으로 해야 합니다.
  • 🤖 AI 지원: GitHub Copilot과 같은 AI 도우미는 BULK COLLECT 및 FORALL 블록을 작성하고 LIMIT 절이 누락되었음을 표시합니다.

Oracle PL/SQL BULK COLLECT 및 FORALL과 LIMIT 절 개요

대량 수집이란 무엇입니까?

BULK COLLECT는 컨텍스트 전환을 줄여줍니다. SQL PL/SQL 엔진을 사용하며, SQL 엔진이 레코드를 한 번에 가져올 수 있도록 합니다.

Oracle PL / SQL BULK COLLECT는 레코드를 하나씩 가져오는 대신 일괄적으로 가져오는 기능을 제공합니다. 이 BULK COLLECT는 SELECT 문에서 레코드를 일괄적으로 채우거나 특정 레코드를 가져오는 데 사용할 수 있습니다. 커서 BULK COLLECT는 레코드를 일괄적으로 가져오기 때문에 INTO 절에는 항상 컬렉션 유형 변수가 포함되어야 합니다. BULK COLLECT를 사용하는 주요 이점은 데이터베이스와 PL/SQL 엔진 간의 상호 작용을 줄여 성능을 향상시키는 것입니다.

구문 :

SELECT <column1> BULK COLLECT INTO bulk_variable FROM <table name>;
FETCH <cursor_name> BULK COLLECT INTO <bulk_variable>;

위 구문에서 BULK COLLECT는 SELECT 및 FETCH 문에서 데이터를 수집하는 데 사용됩니다.

FORALL 조항

FORALL 문은 다음과 같은 작업을 수행합니다. DML 작업 FORALL은 대량의 데이터를 처리하는 데 사용됩니다. FOR 루프 문과 유사하지만, FOR 루프에서는 레코드 단위로 작업이 수행되는 반면, FORALL에는 반복 개념이 없습니다. 대신, 지정된 범위 내의 모든 데이터가 동시에 처리됩니다.

구문 :

FORALL <loop_variable> in <lower range> .. <higher range>

<DML operations>;

위 구문에서, 주어진 DML 작업은 하한 범위와 상한 범위 사이에 있는 전체 데이터에 대해 실행됩니다.

LIMIT 조항

대량 수집(bulk collect) 개념은 전체 데이터를 대상 컬렉션 변수에 일괄적으로 로드하는 방식입니다. 즉, 모든 데이터가 한 번에 컬렉션 변수에 채워집니다. 하지만 로드해야 할 레코드 수가 매우 많은 경우에는 이 방식이 권장되지 않습니다. PL/SQL이 전체 데이터를 로드하려고 하면 세션 메모리를 과도하게 사용하기 때문입니다. 따라서 대량 수집 작업의 크기를 제한하는 것이 좋습니다.

이러한 크기 제한은 SELECT 문에 ROWNUM 조건을 도입함으로써 쉽게 달성할 수 있지만, 커서의 경우에는 이것이 불가능합니다.

이를 극복하기 위해, Oracle 대량 처리에 포함해야 하는 레코드 수를 정의하는 LIMIT 절을 제공했습니다.

구문 :

FETCH <cursor_name> BULK COLLECT INTO <bulk_variable> LIMIT <size>;

위 구문에서 커서 가져오기 문은 LIMIT 절과 함께 BULK COLLECT 문을 사용합니다.

대량 수집 속성

커서 속성과 유사하게, BULK COLLECT에는 FORALL 문의 n번째 DML 문에서 영향을 받은 행 수를 반환하는 %BULK_ROWCOUNT(n) 속성이 있습니다. 즉, 컬렉션 변수의 각 값에 대해 FORALL 문에서 영향을 받은 레코드 수를 제공합니다. 여기서 'n'은 행 수를 계산해야 하는 컬렉션 내 값의 순서를 나타냅니다.

예 1 : 이 예제에서는 BULK COLLECT를 사용하여 emp 테이블에서 모든 직원 이름을 가져오고, FORALL을 사용하여 모든 직원의 급여를 5000만큼 증가시킬 것입니다.

아래 스크린샷은 BULK COLLECT 및 FORALL 예제와 그 출력 결과를 보여줍니다. Oracle.

LIMIT 및 FORALL을 사용한 대량 수집 예시 (직원 급여 업데이트) Oracle PL / SQL

DECLARE
CURSOR guru99_det IS SELECT emp_name FROM emp;
TYPE lv_emp_name_tbl IS TABLE OF VARCHAR2(50);
lv_emp_name lv_emp_name_tbl;
BEGIN
OPEN guru99_det;
FETCH guru99_det BULK COLLECT INTO lv_emp_name LIMIT 5000;
FOR c_emp_name IN lv_emp_name.FIRST .. lv_emp_name.LAST
LOOP
Dbms_output.put_line('Employee Fetched:'||c_emp_name);
END LOOP;
FORALL i IN lv_emp_name.FIRST .. lv_emp_name.LAST
UPDATE emp SET salary=salary+5000 WHERE emp_name=lv_emp_name(i);
COMMIT;
Dbms_output.put_line('Salary Updated');
CLOSE guru99_det;
END;
/

산출

Employee Fetched:BBB
Employee Fetched:XXX
Employee Fetched:YYY
Salary Updated

Code 설명 :

  • Code 2행: 'SELECT emp_name FROM emp' 문에 대한 커서 guru99_det를 선언합니다.
  • Code 3행: lv_emp_name_tbl을 VARCHAR2(50) 테이블 유형으로 선언합니다.
  • Code 4행: lv_emp_name을 lv_emp_name_tbl 형식으로 선언합니다.
  • Code 6행: 커서를 엽니다.
  • Code 7행: BLOK COLLECT를 사용하여 커서를 가져오고, LIMIT 크기를 5000으로 설정하여 lv_emp_name 변수에 저장합니다.
  • Code 8-11행: lv_emp_name 컬렉션의 모든 레코드를 출력하는 FOR 루프를 설정합니다.
  • Code 12행: FORALL 함수를 사용하여 모든 직원의 급여를 5000만큼 업데이트합니다.
  • Code 14행: 저지르다 거래.

자주 묻는 질문

아니요. BULK COLLECT SELECT는 NO_DATA_FOUND 예외를 발생시키지 않고 빈 컬렉션을 반환합니다. 컬렉션을 찾기 전에 항상 .COUNT 메서드를 사용하여 컬렉션의 개수를 확인하세요.ping그렇지 않으면 0개의 행이 처리되어도 아무런 메시지가 표시되지 않을 수 있습니다.

SAVE EXCEPTIONS를 사용하면 개별 행에 오류가 발생하더라도 FORALL이 계속 실행됩니다. 오류가 발생한 행은 SQL%BULK_EXCEPTIONS에 저장됩니다. Oracle ORA-24381 오류가 발생하며, 이 오류는 특정 상황에 갇히게 됩니다. 예외 각 오류를 검사하는 핸들러입니다.

반복문에서 여러 행을 읽을 때는 항상 BULK COLLECT를 사용하십시오. 커서 FOR 루프는 switch 문마다 한 행씩 가져오므로, 대량 가져오기와 FORALL을 함께 사용하면 결과 집합이 클 경우 훨씬 빠르게 실행될 수 있습니다.

BULK COLLECT는 한 번에 여러 행을 반환하므로 다중 행 컨테이너가 필요합니다. INTO 대상은 다중 행 컨테이너여야 합니다. 수집 중첩 테이블, VARRAY 또는 연관 배열과 같은 구조이며, 단일 스칼라 변수가 아닙니다.

아니요. FORALL 헤더는 정확히 하나의 INSERT, UPDATE, DELETE 또는 MERGE 문을 실행합니다. 반복마다 VALUES 및 WHERE 절의 값만 변경될 수 있습니다. 여러 개의 문을 실행하려면 각각 별도의 FORALL 문을 사용하십시오.

대량 처리는 BULK COLLECT 및 FORALL을 사용하여 수천 번의 엔진 컨텍스트 전환을 몇 번으로 압축함으로써 대규모 데이터 처리 시 오버헤드를 크게 줄이기 때문에 행별 코드 처리보다 수 배에서 100배 이상 빠를 수 있습니다.

예. GitHub 부조종사 이 문서에서는 주석을 기반으로 BULK COLLECT 페치, FORALL DML 루프 및 LIMIT 절을 작성하고 컬렉션 유형 선언을 제안하지만 배치 크기 및 오류 처리는 직접 검토해야 합니다.

AI 어시스턴트는 한 번에 한 행씩 가져오거나 변경하는 반복문을 분석하여 BULK COLLECT, LIMIT, FORALL을 사용하여 다시 작성할 것을 권장합니다. 이러한 머신러닝 기반 검토를 통해 프로덕션 환경에 배포하기 전에 누락된 LIMIT 제한이나 성능 병목 현상을 찾아낼 수 있습니다.

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