■ Data Skill ■/PL-SQL

PL/SQL (17) - Collections (Index-by Table)

한길(One Way) 2023. 3. 18.

Collection은 여러 오브젝트를 하나로 묶을 수 있게 해준다.

프로그래밍의 배열과 유사하다.

 

3가지 유형

1. 인덱스 테이블
2. 중첩 테이블
3. 가변 크기 배열 (varray)


1. 인덱스 테이블 (Index-by)

인덱스 테이블이란?

- 테이블의 각 요소가 정수값으로 색인되어 있는 테이블.

- 테이블의 각 요소는 불연속적으로 저장된다.

- 테이블의 최대 크기를 설정하지 못한다.

 

 

인덱스 테이블 TYPE 정의 및 변수 선언

- 먼저 TYPE을 선언하고, 이 TYPE의 변수를 선언한다.

- TYPE은 스칼라(NUMBER,VCHAR2,...)나 레코드(RECORD)가 될 수 있다.

- 테이블의 인덱스에 대한 데이터형은 BINARY_INTEGER 여야 한다.

TYPE 형이름 IS TABLE OF 데이터형 [NOT NULL] INDEX BY BINARY_INTEGER;

 

형이름 : TYPE의 이름. 인덱스 테이블 변수 선언시 해당 이름을 사용하여 형 정의.

데이터형 : Collection의 데이터형. 테이블의 각 요소는 정의한 데이터형으로 된 값을 저장한다.

NOT NULL : 테이블의 항목이 NULL이 되는 것을 금지한다.

 

아래 예를 들어 보자.

DECLARE
TYPE population_type IS TABLE OF NUMBER INDEX BY VARCHAR2(64);
-- 인덱스 테이블 타입 정의. 각 항목은 VARCHAR2(64) 형이 들어갈 수 있다.
-- VARCHAR2 는 oracle 9i 부터 지원된다. 이전 버전엔 BINARY_INTEGER만 지원한다.

TYPE emp_table_type IS TABLE OF employees%ROWTYPE INDEX BY BINARY_INTEGER;
-- 변수 선언시 employees 테이블의 1개 row와 동일한 구조가 생성된다. employees 테이블처럼 여러개의 컬럼을 가진다.
-- 변수에 대한 각각의 컬럼 접근은 점(.)으로 구분한다.

country_population population_type;

continent_population population_type;

l_emp_table emp_table_type;

-- 위에서 정의한 인덱스 테이블 타입 변수 선언.

howmany NUMBER;

somenum NUMBER;

which VARCHAR2(64);


BEGIN
  country_population('Greenland') := 100000; -- Creates new entry
  country_population('Iceland') := 750000;   -- Creates new entry
-- Looks up value associated with a string
  howmany := country_population('Greenland');
  continent_population('Australia') := 30000000;
  continent_population('Antarctica') := 1000; -- Creates new entry
  continent_population('Antarctica') := 1001; -- Replaces previous value 
   l_emp_table(10).employee_id := 10;
   l_emp_table(10).first_name := 'YongWoon';
   l_emp_table(10).last_name := 'Kang';
   l_emp_table(10).email := 'tangamjaelt@korea.com';
-- Returns 'Antarctica' as that comes first alphabetically.
  which := continent_population.FIRST;
-- Returns 'Australia' as that comes last alphabetically.  which := continent_population.LAST;
-- Returns the value corresponding to the last key, in this
-- case the population of Australia.
  howmany := continent_population(continent_population.LAST);
 
   IF continent_population.EXISTS('Greenland') THEN
          somenum := continent_population('Greenland');
   ELSE
          DBMS_OUTPUT.PUT_LINE('Element Greenland does not exist.');
   END IF;
​
END;
/

- 이렇게 인덱스 테이블 변수 country_population 을 선언한 뒤 이를 배열처럼 사용할 수 있다.

- 정의한 타입과 동일한 크기의 기억장소가 동적으로 선언된다.

- 각 기억장소 구분은 테이블변수(index)

 

인덱스 테이블 변수의 값 조작

- 위 예에서 인덱스 테이블 변수 country_population 을 선언하였으니, 이 변수에 값을 할당하고 조작해본다.

- 인덱스 테이블 변수에는 각각에 대해 메소드들이 존재한다.

변수.FIRST : 알파벳 순으로 정렬했을 때 첫번째 항목.

변수.LAST : 알파벳 순으로 정렬했을 때 마지막 항목.

변수.COUNT : 변수 내 항목의 개수를 보여준다.

변수.EXISTS('index') : 지정한 항목이 있는 확인.

변수.DELETE('index') : 지정한 항목을 삭제. 항목을 지정하지 않으면 변수 내 항목 전체를 삭제한다.

변수.NEXT('index') : 지정한 항목 다음 값을 리턴한다.

변수.PRIOR('index') : 지정한 항목 이전 값을 리턴한다.

 

DECLARE  
  TYPE population_type IS TABLE OF NUMBER INDEX BY VARCHAR2(64);
  TYPE emp_table_type IS TABLE OF employees%ROWTYPE INDEX BY BINARY_INTEGER;
  country_population population_type;
  continent_population population_type;
  l_emp_table emp_table_type;
  howmany NUMBER;
  somenum NUMBER;
  which VARCHAR2(64);

BEGIN
  country_population('Greenland') := 100000; -- 새로운 항목 동적으로 생성. 구분자는 Greenland.
  country_population('Iceland') := 750000;   -- 새로운 항목 동적으로 생성. 구분자는 Iceland.
​
  howmany := country_population('Greenland');  -- Greenland 값을 일반 변수 howmany 에 대입
  continent_population('Australia') := 30000000;   
  continent_population('Antarctica') := 1000; -- 새로운 항목 생성. Antarctica.
  continent_population('Antarctica') := 1001; -- Antarctica 를 다른 값으로 대치
 
   l_emp_table(10).employee_id := 10;
   l_emp_table(10).first_name := 'YongWoon';
   l_emp_table(10).last_name := 'Kang';
   l_emp_table(10).email := 'tangamjaelt@korea.com';
-- ROWTYPE 변수이기 때문에 각 항목의 컬럼에 대해 값을 설정해야 한다.
-- 만약 컬럼이 8개인데 위와 같이 4개에만 값을 할당하면 나머지 4개 컬럼은 NULL로 채워진다. 
-- (제약조건이 없을시..)

  which := continent_population.FIRST;  
-- FIRST 메소드.
-- continent_population 변수에 생성된 항목들을 알파벳 순으로 정렬했을 때 첫번째 항목을 리턴한다.
-- which 변수엔 'Antarctica' 가 들어간다.
​
  howmany := continent_population(continent_population.LAST);
-- LAST 메소드는 알파벳 순으로 마지막 항목을 리턴한다.
-- howmany 변수엔 다시 쓰면 continent_population('Iceland') 가 들어가게 되므로, 
-- Iceland 값인 750000 이 들어간다.
 
   IF continent_population.EXISTS('Greenland') THEN 
          somenum := continent_population('Greenland');
-- EXISTS 메소드는 해당 항목이 존재하는지 체크한다.
-- 존재하면 somenum 변수에 해당 값 100000 을 저장한다.
   ELSE
          DBMS_OUTPUT.PUT_LINE('Element Greenland does not exist.');
   END IF;
 
   continent_population.DELETE('Iceland');
-- DELETE 메소드는 해당 항목을 삭제한다. Iceland 항목을 삭제한다.   
-- 숫자의 경우 .DELETE(1,10) 이라고 하면 1부터 10까지 항목을 삭제하게 된다.
-- continent_population.DELETE; 라고 하면 모든 항목이 삭제된다. 

END;
/
 

 

728x90

댓글