바닥코딩
PL/SQL 컬렉션 본문
컬랙션은 내부 구성 항목이 모두 동일한 데이터 타입을 가진 유형의 자료 구조입니다 일반적인 프로그래밍 언어를 학습해 보신분들은 알고 있는 개념일테지만 대표적으로 배열과 같은 구조 등이 컬렉션에 해당합니다. 컬렉션의 각 항복은 변수명(인덱스) 와 같은 표현식을 사용하여 접근이 가능합니다
컬렉션 타입의 종류
오라클 PL/SQL에서 지원하는 컬렉션 타입에는 Associative Array(연관 배열), VARRAY(가변 크기 배열), Nested Table (중첩 테이블) 등이 이에 해당합니다
비교항목 / 컬렉션타입 | Associative Array | VARRAY | Nested Table |
컬렉션 항목의 개수 | 미지정 | 지정 | 미지정 |
인덱스 유형 | 문자열 또는 정수 | 정수 | 정수 |
초기화되지 않은 상태 | Empty | null | null |
ADT(객체타입) | 불가능 | 가능 | 가능 |
Associative Array
Associative Array는 컬렉션 항복의 개수를 사전에 지정하지 않습니다. 인덱스는 정수 또는 문자열을 인덱스로 사용할 수 있는데, 심지어 음수도 사용이 가능합니다 유일하게 초기화를 필요로 하지 않고, 변수는 null을 할당 할 수 없습니다. 정리하지면, Associative Array는 키-값 의 쌍으로 이루어진 무한 배열이라고 볼 수 있습니다.
예제를 통해 알아보겠습니다.
declare
-- 정수를 인덱스로 하는 Associative Array 타입 선언
type city is table of varchar2(64) index by pls_integer ;
-- 문자열을 인덱스로 하는 Associative Array 타입 선언
type population is table of number index by varchar2(64);
v_city city;
v_Population population;
begin
v_city (-1) := '서울';
v_city (0) := '부산';
v_city (2) := '대전';
v_Population('서울') := 10373234 ;
v_Population('부산') := 3812392 ;
v_Population('대전') := 1390510 ;
DBMS_OUTPUT.PUT_LINE('도시별 인구');
DBMS_OUTPUT.PUT_LINE('===========================================');
DBMS_OUTPUT.PUT_LINE(v_city(-1) || ':' ||
to_char(v_Population(v_city(-1)),'999,999,999'));
DBMS_OUTPUT.PUT_LINE(v_city(-1) || ':' ||
to_char(v_Population(v_city(0)),'999,999,999'));
DBMS_OUTPUT.PUT_LINE(v_city(-1) || ':' ||
to_char(v_Population(v_city(2)),'999,999,999'));
end;
위 예제와 같이 Associative Array는 [TYPE 타입명 IS TABLE OF 데이터타입 INDEX BY 인덱스테이터 타입] 형식으로 사용 됩니다. 추가적으로, BULK COLLECT 함수를 사용하면 여러건의 SELECT 결과를 Associative Array 에 담을 수 있습니다.
declare
type string_array is table of varchar2(100) index by pls_integer ;
v_arr string_array;
begin
select ename
bulk collect into v_arr
from emp;
DBMS_OUTPUT.PUT_LINE('Associative Arrat 컬랙션 개수 :' || v_arr.COUNT);
end;
VARRAY(Variable-Size Array)
VARRAY는 우리가 일반적으로 생각하는 그 배열입니다. 일반적으로 다른 프로그래밍 언어에서 선언 하는 것과 비슷하게 VARRAY 는 배얄이 가질 수 있는 사이즈를 지정해야합니다. 또한 반드시 초기화를 해줘야 오류를 미연에 방지하는 것이 가능합니다.
VARRAY는 아래아 같이 선언하고 사용합니다
[TYPE 타입명 IS VARRAY(크기) OF 데이터타입]
다음 예제를 통해 확인해 보겠습니다.
declare
type languages is varray(10) of varchar(64); -- varry 선언
v_lang languages;
v_lang2 languages := languages('한국어', '중국어', '영어');
begin
v_lang := languages();
v_lang := languages('한국어');
v_lang := languages('한국어', '중국어');
v_lang.extend(2); -- 배열 확장 메소드
v_lang(3) := '일본어';
v_lang(4) := '영어';
DBMS_OUTPUT.PUT_LINE('언어 목록' );
dbms_output.PUT_LINE('=============');
for i in v_lang.First .. v_lang.LAST
loop
DBMS_OUTPUT.PUT_LINE(to_char(i)|| ':' || v_lang(i));
end loop;
end;
VARRAY도 Associative Array 와 마찬가지로 BULK COLLECT가 사용 가능 합니다.
--varray bulk collect (select 결과를 varray로 대입)
declare
type string_array is varray(20) of varchar2(100);
v_arr string_array;
begin
select ename bulk collect into v_arr --v_arr 변수에 쿼리 결과 삽입
from emp
where rownum <= 20;
DBMS_OUTPUT.PUT_LINE('varry count :' || v_arr.COUNT);
end;
Nested Table
Nested Table은 순서가 고정되어 있지 않고, 크기도 고정되지 않은 데이터의 집합을 저장하는데 가장 적합한 컬렉션입니다. 컬렉션의 인덱스는 1에서 시작하여 순차적으로 진행합니다 하지만 값을 저장하거나 조회할떄 항목의 순서가 항상 동일함을 보장하지 않습니다. 이 말이 잘 이해가 되지 않을거같아 자세히 서술하자며
- 배열은 크기가 사전에 선언 되지만 Nested Table의 크기는 동적으로 증가한다
- 동적으로 증가하기 떄문에 항상 밀집해 있지 않으며 예를 들어 일부를 삭제하면 현재 데이터 사이 사이 공간이 비어 빈 항목이 존재할 수 있다
등으로 해석할 수 있겠습니다.
Nested Table의 구조는 다음과 같습니다 [TYPE 타입명 IS TABLE OF 데이터타입] 해당 구조는 예제를 통해 더 자세히 알아보겠습니다.
DECLARE
TYPE city IS TABLE OF VARCHAR2(64); -- Nested Table 선언
v_city city;
v_city2 city := city('서울','대전','부산');
BEGIN
v_city := city('서울','대전','부산','광주','인천');
v_city :=city(); -- 초기화
v_city.extend; v_city(1) := '서울'; --Nested Table 값 추가
v_city.extend; v_city(1) := '대전';
v_city.extend; v_city(1) := '부산';
v_city.extend; v_city(1) := '대구';
DBMS_OUTPUT.PUT_LINE('도시개수 :'||v_city.COUNT||'개' );
for i in v_city.FIRST .. v_city.LAST
loop
if v_city.EXISTS(i) then
DBMS_OUTPUT.PUT_LINE(v_city(i));
end if;
end loop;
v_city.delete(3); -- 3번째 항목을 삭제
BMS_OUTPUT.PUT_LINE('도시개수 :'||v_city.COUNT||'개' );
for i in v_city.first .. v_city.LAST
loop
if v_city.EXISTS(i) then
DBMS_OUTPUT.PUT_LINE(v_city(i));
end if;
end loop; -- 삭제된 3번쨰 항목은 출력이 되지 않는다
END;
여기서 데이터를 삭제한 항목은 참조할 수 없으며 항상 순서가 일반적이지 않을 수도 있다는 사실은 유념해야 합니다. 하나더, Nested Table에서도 BULK COLLECT 를 사용할 수 있습니다.
DECLARE
TYPE string_arr IS TABLE OF VARCHAR2(100);
v_arr string_arr;
BEGIN
SELECT ename
BULK COLLECT INTO v_arr
FROM EMP;
DBMS_OUTPUT.PUT_LINE('Nested table 컬렉션 건수 :' || v_arr.COUNT);
END;