source

PL/SQL 대량 수집을 스파스 키를 사용하여 연관 배열로 수집

ittop 2023. 7. 26. 22:25
반응형

PL/SQL 대량 수집을 스파스 키를 사용하여 연관 배열로 수집

PL/SQL 내부에서 SQL 쿼리를 실행하여 결과를 연관 배열로 채우고 SQL의 열 중 하나가 연관 배열의 키가 됩니다.예를 들어 테이블이 있다고 가정합니다.Person열이 있는

PERSON_ID   INTEGER      PRIMARY KEY
PERSON_NAME VARCHAR2(50)

...다음과 같은 값이 있습니다.

 PERSON_ID  |  PERSON_NAME
 ------------------------
 6          |  Alice
 15         |  Bob
 1234       |  Carol

나는 이 테이블을 대량으로 수집하고 싶습니다.TABLE OF VARCHAR2(50) INDEX BY INTEGER열쇠가 되도록6이 연상 배열에서 값은 다음과 같습니다.Alice등등.PL/SQL에서 수행할 수 있습니까?만약 그렇다면, 어떻게?

아니요, 두 개의 컬렉션(ID, 이름) 또는 요소 유형이 레코드인 컬렉션을 사용해야 합니다.

후자의 예는 다음과 같습니다.

  cursor getPersonsCursor is
    SELECT ID, Name
    FROM   Persons
    WHERE  ...;

  subtype TPerson is getPersonsCursor%rowtype;
  type TPersonList is table of TPerson;
  persons TPersonList;
begin

open getPersonsCursor;
fetch getPersonsCursor
  bulk collect into persons;
close getPersonsCursor;

if persons.Count > 0 then
  for i in persons.First .. persons.Last loop
    yourAssocArray(persons(i).ID) := persons(i).Name;
  end loop;
end if;

연관 배열의 인덱스에 값을 지정하려면 다음 구문을 사용해야 합니다.

SQL> declare
  2      type n_array is table of varchar2(30)
  3           index by binary_integer;
  4      emp_names n_array;
  5  begin
  6      for r in ( select ename, empno from emp )
  7      loop
  8          emp_names(r.empno) := r.ename;
  9      end loop;
 10
 11      dbms_output.put_line('count='||emp_names.count()
 12                               ||'::last='||emp_names.last());
 13      dbms_output.put_line(emp_names(8085));
 14
 15  end;
 16  /
count=19::last=8085
TRICHLER

PL/SQL procedure successfully completed.

SQL>

대량 수집을 사용하여 연관 배열을 채울 수 있지만 인덱스가 정수이고 (암묵적인) ROWNUM(즉, 희소 키가 아닌)을 사용하여 인덱싱할 수 있습니다.

SQL> declare
  2      type n_array is table of varchar2(30)
  3           index by binary_integer;
  4      emp_names n_array;
  5  begin
  6      select ename
  7      bulk collect into emp_names
  8      from emp ;
  9
 10      dbms_output.put_line('count='||emp_names.count()
 11                               ||'::last='||emp_names.last());
 12      dbms_output.put_line(emp_names(19));
 13
 14  end;
 15  /
count=19::last=19
FEUERSTEIN

PL/SQL procedure successfully completed.

SQL>

공정하게 말하자면, BULK COLLECT를 사용해야 하는 경우에는 연관 배열에 적합한 것보다 더 많은 데이터를 처리하고 있을 수 있습니다.

편집

두 가지 접근 방식에 대한 저렴한 성능 테스트:

SQL> declare
  2      type n_array is table of varchar2(30)
  3           index by binary_integer;
  4      emp_names n_array;
  5      s_time pls_integer;
  6      e_time pls_integer;
  7  begin
  8      s_time := dbms_utility.get_time;
  9      select ename
 10      bulk collect into emp_names
 11      from big_emp
 12      where rownum <= 500;
 13      dbms_output.put_line('bulk collect elapsed time = '
 14                              ||to_char(dbms_utility.get_time - s_time));
 15      s_time := dbms_utility.get_time;
 16      for r in ( select ename, empno from big_emp
 17                 where rownum <= 500 )
 18      loop
 19          emp_names(r.empno) := r.ename;
 20      end loop;
 21      dbms_output.put_line('sparse array elapsed time = '
 22                              ||to_char(dbms_utility.get_time - s_time));
 23  end;
 24  /

bulk collect elapsed time = 0
sparse array elapsed time = 0

PL/SQL procedure successfully completed.

SQL>

벽시계 성능 테스트는 거친 것으로 악명이 높습니다.하지만 수백 개의 기록에 대해서는, 어떤 차이도 걱정할 가치가 없을 것 같습니다. 확실히 우리가 연상배열을 사용하고 싶어하는 곳의 맥락에서 말입니다.

편집 2

@댄이 말했습니다.

일정한 시간 검색에 사용할 수 있는 데이터 구조에 적절한 크기의 행 수를 쿼리하는 것이 상당히 일반적인 요구 사항인 것 같습니다.

그것은 정말로 "적당한 크기의 숫자"에 대한 당신의 정의에 달려 있습니다.수천 개의 행과 문자열 인덱스가 있는 연관 배열을 채우는 경우가 정말 그렇게 많습니까?이러한 수치에 도달하면 일반적인 데이터베이스 테이블도 마찬가지로 유용할 수 있습니다. 특히 11g Enterprise Edition에서는 결과 집합 캐싱이 가능합니다.

언급URL : https://stackoverflow.com/questions/2715736/pl-sql-bulk-collect-into-associative-array-with-sparse-key

반응형