IT, 프로그래밍/Database (Oracle)

[PL/SQL] 컬렉션(Collection) - 개념

오리@ 2019. 1. 23. 09:12




Collection = 다양한 데이터 타입을 가질 수 있는 동시에, 여러 로우에 해당하는 데이터를 가질 수 있는 자료형.


특징


생성자를 이용해 초기화 가능

빌트인 함수와 프로시저로 구성된 컬렉션 메소드 제공




1) 연관 배열(Associative Array)


키와 값으로 구성된 컬렉션. 키를 Index라고 부르기 때문에 Index-by 테이블 이라고도 함.

자바에 있는 Map 구조에 대응되는 컬렉션이다.




TYPE 이름 IS TABLE OF 값타입 INDEX BY 인덱스타입;


으로 정의하여 사용한다.


인덱스타입 = 키 타입임.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
DECLARE
 
    TYPE av_type IS TABLE OF VARCHAR2(40)
                    INDEX BY PLS_INTEGER;
    vav_test av_type;
 
BEGIN
 
    vav_test(10) := '이것은 10에 대한 값임';
    vav_test(20) := '이것은 20에 대한 값임';
 
    DBMS_OUTPUT.PUT_LINE(VAV_TEST(10));
    DBMS_OUTPUT.PUT_LINE(VAV_TEST(20));
 
END;
cs


PL/SQL 프로시저가 성공적으로 완료되었습니다.

이것은 10에 대한 값임
이것은 20에 대한 값임


인덱스 타입을 정수형으로 하고, 값은 문자타입으로 설정하였다.

설정한 대로 데이터가 잘 들어가는 것을 확인할 수 있다.

만약 인덱스에 숫자가 아닌 타입을 넣으면 어떻게 될까?

1
2
3
4
5
6
 
BEGIN
    vav_test('숫자 10') := '이것은 10에 대한 값임';
    vav_test(20) := '이것은 20에 대한 값임';
.....
 
cs



END;

오류 보고 -

ORA-06502: PL/SQL: numeric or value error: character to number conversion error

ORA-06512: at line 9


컴파일 에러를 발생시키며 적절한 키 값이 아니라고 나온다.




2. 가변 길이 배열 (VARRY, Variable-Size Array)





선언할 때 크기(요소 개수)를 지정한 만큼 배열을 만든다. 일반적인 프로그래밍 언어에서 지원하는 배열(Array)에 해당함.

중요한 것은 요소 크기가 크더라도, 원소를 요소 크기 이하로 초기화하면 그 만큼만 초기화된다.




Type 이름 IS VARRY(최대 크기) OF 배열 요소의 타입



생성자가 사용해 초기화하기 전 까지 각 요소에 값을 할당하거나 읽어올 수 없음. 

생성자는 배열명(값1, 값2, 값3.... ) 형태로 사용. 

NULL값으로 초기화 하면 해당 요소는 참조가 가능.

기본으로 NULL값으로 참조되지 않는다. 만약 5개의 배열에 3개만 초기화 시켰다면 나머지 인덱스에는 접근이 불가능하다.


* 시작 인덱스는 1부터 시작한다. 0이 아니다. 1부터 시작한다. 이 점을 꼭 유의할 것 !!



 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
DECLARE
 
    TYPE va_type IS VARRAY(5) OF VARCHAR2(20);
    vva_test va_type;
 
BEGIN
    vva_test := va_type('FIRST''SECOND''THIRD''''');
    FOR i IN 1..5
    LOOP
    DBMS_OUTPUT.PUT_LINE(vva_test(i));
    END LOOP;
  
END;
 
cs


FIRST

SECOND

THIRD





초기화 시킨 대로 값이 나오는 것을 확인할 수 있다.


그럼 여기서 3번째 자리에 값을 넣어보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 
DECLARE
 
    TYPE va_type IS VARRAY(5) OF VARCHAR2(20);
    vva_test va_type;
 
BEGIN
    vva_test := va_type('FIRST''SECOND''THIRD''''');
   
    FOR i IN 1..5
    LOOP
    DBMS_OUTPUT.PUT_LINE(vva_test(i));
    END LOOP;
    
    vva_test(3) := '네번째';
   
    FOR j IN 1..5
    LOOP
    DBMS_OUTPUT.PUT_LINE(vva_test(j));
    END LOOP;
    
  
END;
 
cs




FIRST

SECOND

THIRD


FIRST

SECOND

네번째





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
DECLARE
 
    TYPE va_type IS VARRAY(5) OF VARCHAR2(20);
    vva_test va_type;
 
BEGIN
    vva_test := va_type('FIRST''SECOND''THIRD');
   
    FOR i IN 1..3
    LOOP
    DBMS_OUTPUT.PUT_LINE(vva_test(i));
    END LOOP;
    DBMS_OUTPUT.PUT_LINE(vva_test(4));
 
END;
cs



3번째 인덱스까지 초기화 하였으나 4번째 인덱스에 접근하였다.



END;

오류 보고 -

ORA-06533: Subscript beyond count

ORA-06512: at line 13

06533. 00000 -  "Subscript beyond count"

*Cause:    An in-limit subscript was greater than the count of a varray



초기화 되지 않는 인덱스이므로 당연히 에러가 발생한다.


가변 배열의 경우, 초기화 되는 경우 5개 크기의 배열을 선언하였지만, 3개를 초기화 하였으면 3개의 크기만큼만 배열이 잡히는 것을 유의하자.


1
2
3
4
5
6
7
8
9
DECLARE
 
    TYPE va_type IS VARRAY(5) OF INTEGER;
    vva_test va_type;
 
BEGIN
    vva_test := va_type(123);
   
END;
cs




실제 초기화 된 가변 배열의 모습이다.







3. 중첩 테이블 (Nested Table)





연관 배열과 비슷한 모양이나, 인덱스가 모두 숫자로 되어있다.

연관배열과 가변배열을 합친 모습의 컬렉션이며 가변 배열과 비슷하게 제어할 수 있다.

예를 들어, for문을 통해 순회할 수 있으며 초기화도 비슷하게 이루어진다.


TYPE 이름 IS TABLE OF 값 데이터 타입;


1
2
3
4
5
6
7
8
9
10
11
DECLARE
TYPE nt_typ IS TABLE OF VARCHAR2(10);
    vnt_test nt_typ;
BEGIN
    vnt_test := nt_typ('FIRST''SECOND''THIRD');
 
    FOR i IN 1..3
LOOP
    DBMS_OUTPUT.PUT_LINE(vnt_test(i));
END LOOP;
END;
cs


FIRST

SECOND

THIRD