2010-04-26 3 views
10

PL/SQL 내부에서 SQL 쿼리를 실행하고 SQL의 열 중 하나가 연관 배열의 키가되는 연관 배열에 결과를 채 웁니다. 이 연관에 TABLE OF VARCHAR2(50) INDEX BY INTEGER 등이 주요 6에이 표를 수집스파 스 키를 사용하여 연관 배열로 PL/SQL 대량 수집

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

나는 대량 원하는 예를 들어, 내가 열

PERSON_ID INTEGER  PRIMARY KEY 
PERSON_NAME VARCHAR2(50) 

있는 테이블 Person이 있다고 ... 그리고 값처럼 배열의 값은 Alice입니다. PL/SQL에서이를 수행 할 수 있습니까? 그렇다면 어떻게?

답변

14

아니요, 컬렉션 2 개 (id, name) 또는 요소 유형이 레코드 인 하나를 사용해야합니다. 여기

은 후자의 예이다 :

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; 
+1

+1. 행 수가 매우 많거나 큰 경우 LIMIT 절을 사용하여 과도한 PGA 메모리 소비를 방지하십시오. –

+0

그래, 더 나은 확장을 허용하기 위해서도 그렇게한다. 그래도 조금 이상 할 것 같아. –

6

우리는이 구문을 사용하는 연관 배열의 인덱스 값을 우리가 한 지정하려면 :

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

@Dan는 말했다 :

t 나에게 보인다 정속 사용할 수있는 데이터 구조에 행의 괜찮은 크기의 수를 조회하고자하는 조회한다고 시간이

가 정말 당신에 따라 달라 꽤 일반적인 요구를 할 수 "알맞은 크기의 숫자"의 정의. 수천 개의 행을 가진 연관 배열을 문자열 인덱스로 채우려는 많은 경우가 실제로 있습니까? 우리가 이러한 종류의 숫자에 도달 할 때 일반적인 데이터베이스 테이블이 유용 할 수 있습니다. 특히 11g Enterprise Edition with resultset caching.

+0

몇 명입니까? 필자의 이해로는 상대적으로 적은 수의 행 (예 : 몇 백 개)에 대해서도 SQL에서 PL/SQL 컨텍스트로 전환하는 오버 헤드가 BULK COLLECT를 사용하는 것이 좋습니다. 귀하의 첫 번째 예제 (커서에 대한 루프)에 그 문제가 있습니까? – Dan

+2

FEUERSTEIN 자신이 권고했듯이 커서의 FOR 루프는 절대로 적은 수의 행 (수백 개)을 처리하지 않는 한 절대로 사용하지 마십시오. (또는 단순히 성능에 대해 신경을 쓰지 마십시오.) –

+0

흠. 그렇다면 올바른 대답은 무엇입니까? 알맞은 크기의 행 수를 일정 시간 조회에 사용할 수있는 데이터 구조로 쿼리하려면 꽤 일반적인 필요가 있어야한다고 생각합니다. – Dan

관련 문제