PDH 개발 공부
[개발자를 위한 PL/SQL] 11장 - 컬렉션 본문
- PL/SQL 은 단일 값 데이터 타입 , 복합 데이터 타입 2가지를 지원을 한다.
- 복합 데이터 타입으로 컬렉션과 레코드를 지원
- 컬렉션은 동일한 데이터 타입을 반복되는 데이터를 저장하는 자료구조
- 레코드는 서로 다른 데이터 타입의 데이터를 모아 놓은 자료구조
컬렉션 타입의 종류
- Associative Array : 키와 값으로 구성된 Map
- VARRAY : 선언할 때 크기(요소 개수)를 지정한 만큼 배열을 만든다. 일반적인 프로그래밍 언어에서 지원하는 배열(Array)에 해당함.
- Nested Table : 연관 배열과 비슷한 모양이나, 인덱스가 모두 숫자로 되어있다. 연관배열과 가변배열을 합친 모습의 컬렉션이며 가변 배열과 비슷하게 제어할 수 있다.
예를 들어, for문을 통해 순회할 수 있으며 초기화도 비슷하게 이루어진다.
// REM VARRAY를 사용한 스키마 레벨 데이터 타입 정의
CREATE OR REPLACE TYPE languages IS VARRAY(10) OF VARCHAR2(64)
// REM Nested Table을 사용한 스키마 레벨 데이터 타입 정의
CREATE OR REPLACE TYPE cities IS TABLE OF VARCHAR2(64)
Associative Array 사용법
- NULL이 될수 없다 (할당 시 오류 발생)
- 정수와 문자열 둘중 하나 사용 가능
TYPE 타입명 IS TABLE OF 데이터타입 INDEX BY 인덱스데이터타입;
변수명 타입명 ;
후 변수를 선언해서 사용하면 된다.
예시 1)
DECLARE
TYPE int_array IS TABLE OF PLS_INTEGER INDEX BY PLS_INTEGER; -- Associative Array ADT
v_fibonacci int_array ; -- 피보나치 수열을 저장할 배열
c_order CONSTANT PLS_INTEGER := 20 ;
/*
* N 개의 피보나치 수열을 계산하여 배열을 반환하는 함수
* 피보나치 수열은 처음 두 개의 항이 0과 1이고, 세 번째 항부터는
* F(n) = F(n-1) + F(n-2)의 점화식으로 주어지는 수열이다.
*/
FUNCTION fibonacci_sequence(num IN PLS_INTEGER) RETURN int_array
IS
v_arr int_array; -- 반환할 피보나치 수열(Associative Array)
BEGIN
v_arr(1) := 0 ; -- 첫 번째 항
v_arr(2) := 1 ; -- 2 번째 항
FOR i IN 3..num LOOP -- 3번째 항 이상
v_arr(i) := v_arr(i-1) + v_arr(i-2) ;
END LOOP;
RETURN v_arr ; -- Associative Array를 반환
END ;
BEGIN
v_fibonacci := fibonacci_sequence(c_order) ; -- 함수가 반환한 Associative Array
DBMS_OUTPUT.PUT_LINE('피보나치 수열의 '||c_order||'개 항') ;
FOR i IN 1 .. c_order
LOOP
DBMS_OUTPUT.PUT(CASE WHEN 1 < i THEN ', ' END || v_fibonacci(i)) ;
END LOOP ;
DBMS_OUTPUT.PUT_LINE('') ;
END;
예시 2)
하나하나 할당 해주는 방법이 있지만 이런 방법도 있다.
REM BULK COLLECT를 사용하면 여러 건의 SELECT 결과를
REM Associative Array 변수에 넣을 수 있다.
DECLARE
TYPE string_array IS TABLE OF VARCHAR2(100) INDEX BY PLS_INTEGER;
v_arr string_array ;
BEGIN
-- 테이블 emp의 모든 로우의 ename을 Associative Array 컬렉션에 한 번에 적재한다.
SELECT ename
BULK COLLECT INTO v_arr
FROM emp ;
DBMS_OUTPUT.PUT_LINE('Associative Array 컬렉션 건수 = '||v_arr.COUNT) ;
END ;
VARRAY 사용법**
- 인덱스는 1부터 시작하는 자연수 값
- 초기화 되지 않는 변수는 NULL
TYPE 타입명 IS VARRAY(크기) OF 데이터타입;
변수명 타입명 ;
예시)1
DECLARE
-- VARRAY 타입 선언 : 자연수를 인덱스로 하는, 최대 10개의 64바이트 문자열의 배열
TYPE languages IS VARRAY(10) OF VARCHAR2(64);
v_lang languages ; -- VARRAY 변수 선언. v_lang = NULL임
v_lang2 languages := languages('한국어', '중국어', '영어') ; -- 변수 선언 시 생성자를 사용하여 초기화
BEGIN
v_lang := languages() ; -- 컬렉션 생성자를 사용하여 Empty(크기가 0)로 초기화.
v_lang := languages('한국어') ; -- 컬렉션 생성자를 사용하여 크기가 1인 VARRAY로 재초기화
v_lang := languages('한국어', '중국어') ; -- 컬렉션 생성자를 사용하여 크기가 2인 VARRAY로 재초기화
v_lang.EXTEND(2) ; -- 크기 두 개 증가
v_lang(3) := '일본어' ;
v_lang(4) := '영어' ;
-- v_lang에 들어 있는 언어 출력
DBMS_OUTPUT.PUT_LINE(' ') ;
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 ;
예시2)
BULK COLLECT는 여러 건의 SELECT 결과를 VARRAY 변수에 넣는다
DECLARE
TYPE string_array IS VARRAY(20) OF VARCHAR2(100) ;
v_arr string_array ;
BEGIN
-- 테이블 emp의 모든 로우의 ename을 VARRAY 컬렉션에 한 번에 적재한다.
SELECT ename
BULK COLLECT INTO v_arr
FROM emp
WHERE ROWNUM <= 20 ;
DBMS_OUTPUT.PUT_LINE('VARRAY 컬렉션 건수 = '||v_arr.COUNT) ;
END ;
Nested Table 사용법
순서가 고정되어 있지 않고 크기도 고정되지 않는 데이터의 집합을 저장하는데 적합한 컬렉션
TYPE 타입명 IS TABLE OF 데이터타입 ;
변수명 타입명;
예시)1
DECLARE
-- 정수를 인덱스로 하는 Nested Table
TYPE city IS TABLE OF VARCHAR2(64) ;
-- 빈 컬렉션 변수 선언
v_city city ;
-- 컬렉션 변수 선언과 동시에 컬렉션 생성자를 사용하여 값을 초기화
v_city2 city := city('서울', '부산', '대전') ;
BEGIN
-- 실행 중에도 컬렉션 생성자를 사용하여 초기화 가능
v_city := city('서울', '부산', '대전', '광주', '인천') ;
v_city := city() ; -- 크기 0(Empty 컬렉션)으로 초기화
-- 크기를 증가시키고, 값을 지정한다.
v_city.EXTEND ; v_city(1) := '서울' ;
v_city.EXTEND ; v_city(2) := '부산' ;
v_city.EXTEND ; v_city(3) := '대구' ;
v_city.EXTEND ; v_city(4) := '광주' ;
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(CHR(9)||'v_city(' || TO_CHAR(i) || ') : ' ||v_city(i)) ;
END IF ;
END LOOP ;
-- 3번 인덱스를 삭제한다. 삭제된 인덱스의 항목은 더 이상 접근이 불가능하다.
v_city.DELETE(3) ;
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(CHR(9)||'v_city(' || TO_CHAR(i) || ') : ' ||v_city(i)) ;
END IF ;
END LOOP ;
END ;
'DataBase > PL-SQL' 카테고리의 다른 글
[개발자를 위한 PL-SQL] 12장 - 레코드 (0) | 2021.06.30 |
---|