데이터베이스/oracle

CHAPTER 17. 레코드와 컬렉션-DO IT!오라클로 배우는 데이터베이스 입문

nyeongha 2024. 7. 18. 23:07

CHAPTER17. 레코드와 컬렉션

17-1 자료형이 다른 여러 데이터를 저장하는 레코드

레코드란?

레코드는 자료형이 각기 다른 데이터를 하나의 변수에 저장하는데 사용

TYPE 레코드이름 IS RECORD(
변수이름 자료형 NOT NULL := (또는 DEFAULT) 값 또는 값이 도출되는 여러 표현식
)

자료형에 %TYPE,%ROWTYPE지정이 가능

프로그래밍 언어의 구조체, 클래스 개념과 비슷

정의한 레코드는 기존 자료형 처럼 사용할 수 있음

레코드에 포함된 변수는 레코드 이름과 마침표(.)로 사용할 수 있음

DECLARE
   TYPE REC_DEPT IS RECORD(
      deptno NUMBER(2) NOT NULL := 99,
      dname DEPT.DNAME%TYPE,
      loc DEPT.LOC%TYPE
   );
   dept_rec REC_DEPT;    --선언한 레코드형으로 변수 선언
BEGIN
   dept_rec.deptno := 99;
   dept_rec.dname := 'DATABASE';
   dept_rec.loc := 'SEOUL';
   DBMS_OUTPUT.PUT_LINE('DEPTNO : ' || dept_rec.deptno);
   DBMS_OUTPUT.PUT_LINE('DNAME : ' || dept_rec.dname);
   DBMS_OUTPUT.PUT_LINE('LOC : ' || dept_rec.loc);
END;
/

레코드를 사용한 INSERT

레코드를 사용할 테이블 DEPT_RECORD생성

CREATE TABLE DEPT_RECORD
AS SELECT * FROM DEPT;

SELECT * FROM DEPT_RECORD;

INSERT문에 레코드를 사용하면 VALUES절에 레코드 이름만 명시해도 됨

선언한 레코드와 INSERT대상이 되는 테이블의 데이터 갯수,자료형,순서를 맞추어야 함

DECLARE
   TYPE REC_DEPT IS RECORD(
      deptno NUMBER(2) NOT NULL := 99,
      dname DEPT.DNAME%TYPE,
      loc DEPT.LOC%TYPE
   );
   dept_rec REC_DEPT;
BEGIN
   dept_rec.deptno := 99;
   dept_rec.dname := 'DATABASE';
   dept_rec.loc := 'SEOUL';

   INSERT INTO DEPT_RECORD
   VALUES dept_rec;
END;
/

레코드를 사용한 UPDATE

SET절은ROW키워드와 함께 레코드 이름을 명시

레코드에 저장된 데이터를 사용하여 행 전체의 데이터를 바꿔줌

DECLARE
   TYPE REC_DEPT IS RECORD(
      deptno NUMBER(2) NOT NULL := 99,
      dname DEPT.DNAME%TYPE,
      loc DEPT.LOC%TYPE
   );
   dept_rec REC_DEPT;
BEGIN
   dept_rec.deptno := 50;
   dept_rec.dname := 'DB';
   dept_rec.loc := 'SEOUL';

   UPDATE DEPT_RECORD
      SET ROW = dept_rec
    WHERE DEPTNO = 99;
END;
/

SELECT * FROM DEPT_RECORD;

레코드를 포함하는 레코드

레코드에 포함된 변수의 자료형을 지정할 때 다른 레코드를 지정할 수도 있음

레코드 역시 자료형이기 떄문

중첩 레코드 : 레코드 안에 또 다른 레코드를 포함한 형태,변수에 레코드 형을 적용했으므로 두 개의 마침표(.)로 값을 사용

DECLARE
   TYPE REC_DEPT IS RECORD(
      deptno DEPT.DEPTNO%TYPE,
      dname DEPT.DNAME%TYPE,
      loc DEPT.LOC%TYPE
   );
   TYPE REC_EMP IS RECORD(
      empno EMP.EMPNO%TYPE,
      ename EMP.ENAME%TYPE,
      dinfo REC_DEPT
   );
   emp_rec REC_EMP;
BEGIN
   SELECT E.EMPNO, E.ENAME, D.DEPTNO, D.DNAME, D.LOC
     INTO emp_rec.empno, 
			    emp_rec.ename,
          emp_rec.dinfo.deptno,
          emp_rec.dinfo.dname,
          emp_rec.dinfo.loc
     FROM EMP E, DEPT D
    WHERE E.DEPTNO = D.DEPTNO
      AND E.EMPNO = 7788;

   DBMS_OUTPUT.PUT_LINE('EMPNO : ' || emp_rec.empno);
   DBMS_OUTPUT.PUT_LINE('ENAME : ' || emp_rec.ename);
   DBMS_OUTPUT.PUT_LINE('DEPTNO : ' || emp_rec.dinfo.deptno);
   DBMS_OUTPUT.PUT_LINE('DNAME : ' || emp_rec.dinfo.dname);
   DBMS_OUTPUT.PUT_LINE('LOC : ' || emp_rec.dinfo.loc);
END;
/

17-2 자료형이 같은 여러 데이터를 저장하는 컬렉션

컬렉션 : 특정 자료형의 데이터를 여러 개 저장하는 복합 자료형

여러 종류(여러 타입)의 데이터를 하나로 묶어 사용하는 레코드를 테이블의 한 행처럼 사용한다면,

컬렉션은 열 또는 테이블과 같은 형태로 사용할 수 있음

PL/SQL에서 사용할 수 있는 컬렉션

- 연관 배열(ASSOCIATIVE ARRAY OR INDEX BY TABLE)
- 중첩 테이블(NESTED TABLE)
- VARRAY(VARIABLE-SIZE ARRAY)

연관 배열

연관 배열 : 인덱스라고 불리는 키,값으로 구성되는 컬렉션

중복 되지 않은 유일한 키를 통해 값을 저장하고 불러오는 방식을 사용

연관 배열을 정의할 때 자료형이 TABLE인 변수를 다음과 같이 작성

TYPE 연관 배열 이름 IS TABLE 자료형 [NOT NULL]    --1
INDEX BY 인덱스형;     --2
  1. 연관 배열 열에 사용할 자료형에는 VARCHAR2,DATE,NUMBER와 같은 단일 자료형을 지정할 수 있으며 %TYPE,%ROWTYPE같은 참조 자료형도 사용할 수 있음
  2. NOT NULL 옵션을 사용할 수 있으며 생략 가능
  3. 키로 사용할 인덱스의 자료형을 지정
  4. BINARY_INTEGER,PLS_INTEGER 같은 정수 또는 VARCHAR2같은 문자 자료형도 사용

정의한 연관배열은 레코드와 마찬가지로 특정 변수의 자료형으로 사용 가능

DECLARE
	--인덱스값을 정수로 사용하여 값을 저장하는 연관 배열 정의
   TYPE ITAB_EX IS TABLE OF VARCHAR2(20)
      INDEX BY PLS_INTEGER;

   text_arr ITAB_EX;

BEGIN
   text_arr(1) := '1st data';
   text_arr(2) := '2nd data';
   text_arr(3) := '3rd data';
   text_arr(4) := '4th data';

   DBMS_OUTPUT.PUT_LINE('text_arr(1) : ' || text_arr(1));
   DBMS_OUTPUT.PUT_LINE('text_arr(2) : ' || text_arr(2));
   DBMS_OUTPUT.PUT_LINE('text_arr(3) : ' || text_arr(3));
   DBMS_OUTPUT.PUT_LINE('text_arr(4) : ' || text_arr(4));
END;
/

레코드를 활용한 연관 배열

연관 배열의 자료형으로 레코드 사용 가능

이 경우 다양한 자료형을 포함한 레코드를 여러 개 사용할 수 있으므로 마치 테이블과 같은 데이터 사용과 저장이 가능

DECLARE
   TYPE REC_DEPT IS RECORD(
      deptno DEPT.DEPTNO%TYPE,
      dname DEPT.DNAME%TYPE
   );

   TYPE ITAB_DEPT IS TABLE OF REC_DEPT
      INDEX BY PLS_INTEGER;

   dept_arr ITAB_DEPT;
   idx PLS_INTEGER := -1;

BEGIN
   FOR i IN (SELECT DEPTNO, DNAME FROM DEPT) LOOP
      idx := idx + 1;
      dept_arr(idx).deptno := i.DEPTNO;
      dept_arr(idx).dname := i.DNAME;

      DBMS_OUTPUT.PUT_LINE(
         dept_arr(idx).deptno || ' : ' || dept_arr(idx).dname);
   END LOOP;
END;
/

특정 테이블의 전체 열과 같은 구성을 가진 연관 배열을 제작한다면 다음과 같이 %ROWTYPE을 사용하는 것이 레코드를 정의하는 것보다 간편

DECLARE
   TYPE ITAB_DEPT IS TABLE OF DEPT%ROWTYPE
      INDEX BY PLS_INTEGER;

   dept_arr ITAB_DEPT;
   idx PLS_INTEGER := 0;

BEGIN
   FOR i IN(SELECT * FROM DEPT) LOOP
      idx := idx + 1;
      dept_arr(idx).deptno := i.DEPTNO;
      dept_arr(idx).dname := i.DNAME;
      dept_arr(idx).loc := i.LOC;

      DBMS_OUTPUT.PUT_LINE(
      dept_arr(idx).deptno || ' : ' ||
      dept_arr(idx).dname || ' : ' ||
      dept_arr(idx).loc);
   END LOOP;
END;
/
10 : ACCOUNTING
20 : RESEARCH
30 : SALES
40 : OPERATIONS

컬렉션 메서드

컬렉션 메서드는 컬렉션과 관련된 다양한 정보 조회 기능을 제공

컬렉션 내의 데이터 삭제나 컬렉션 크기 조절을 위한 특정 조작도 가능

메서드 설  명

EXISTS(n) 컬렉션에서  n 인덱스의 데이터 존재 여부를  true / false 로 반환
COUNT 컬렉션에 포함되어 있는 요소 개수를 반환
LIMIT 현재 컬렉션의 최대 크기 반환최대 크기가 없으면  NULL 반환
FIRST 컬렉션의 첫 번째 인덱스 번호 반환
LAST 컬렉션의 마지막 인덱스 번호 반환
PRIOR(n) 컬렉션에서  n 인덱스 바로 앞 인덱스 값을 반환대상 인덱스 값이 존재하지 않으면  NULL 을 반환
NEXT(n) 컬렉션에서 n인덱스 바로 다음 인덱스 값을 반환대상 인덱스 값이 존재하지 않는다면  NULL 을 반환
DELETE 컬렉션에 저장된 요소를 지우는데 사용-  DELETE  : 컬렉션에 저장되어 있는 모든 요소 삭제-  DELETE(n)  :  n 인덱스의 컬렉션 요소를 삭제-  DELETE(n, m) :  n 인덱스 ~  m 인덱스 까지 요소를 삭제
EXTEND 컬렉션 크기를 증가시킴. 연관 배열을 제외한 중첩 테이블과  VARRAY 에서 사용
TRIM 컬렉션 크기를 감소시킴. 연관 배열을 제외한 중첩 테이블과  VARRAY 에서 사용

컬렉션 메서드는 컬렉션 형으로 선언한 변수에 마침표(.)와 함께 작성하여 사용

DECLARE
   TYPE ITAB_EX IS TABLE OF VARCHAR2(20)
      INDEX BY PLS_INTEGER;

   text_arr ITAB_EX;

BEGIN
   text_arr(1) := '1st data';
   text_arr(2) := '2nd data';
   text_arr(3) := '3rd data';
   text_arr(50) := '50th data';

   DBMS_OUTPUT.PUT_LINE('text_arr.COUNT : ' || text_arr.COUNT);
   DBMS_OUTPUT.PUT_LINE('text_arr.FIRST : ' || text_arr.FIRST);
   DBMS_OUTPUT.PUT_LINE('text_arr.LAST : ' || text_arr.LAST);
   DBMS_OUTPUT.PUT_LINE('text_arr.PRIOR(50) : ' || text_arr.PRIOR(50));
   DBMS_OUTPUT.PUT_LINE('text_arr.NEXT(50) : ' || text_arr.NEXT(50));

END;
/
text_arr.COUNT : 4
text_arr.FIRST : 1
text_arr.LAST : 50
text_arr.PRIOR(50) : 3
text_arr.NEXT(50) : 

CHAPTER17. 레코드와 컬렉션

17-1 자료형이 다른 여러 데이터를 저장하는 레코드

레코드란?

레코드는 자료형이 각기 다른 데이터를 하나의 변수에 저장하는데 사용

TYPE 레코드이름 IS RECORD(
변수이름 자료형 NOT NULL := (또는 DEFAULT) 값 또는 값이 도출되는 여러 표현식
)

자료형에 %TYPE,%ROWTYPE지정이 가능

프로그래밍 언어의 구조체, 클래스 개념과 비슷

정의한 레코드는 기존 자료형 처럼 사용할 수 있음

레코드에 포함된 변수는 레코드 이름과 마침표(.)로 사용할 수 있음

DECLARE
   TYPE REC_DEPT IS RECORD(
      deptno NUMBER(2) NOT NULL := 99,
      dname DEPT.DNAME%TYPE,
      loc DEPT.LOC%TYPE
   );
   dept_rec REC_DEPT;    --선언한 레코드형으로 변수 선언
BEGIN
   dept_rec.deptno := 99;
   dept_rec.dname := 'DATABASE';
   dept_rec.loc := 'SEOUL';
   DBMS_OUTPUT.PUT_LINE('DEPTNO : ' || dept_rec.deptno);
   DBMS_OUTPUT.PUT_LINE('DNAME : ' || dept_rec.dname);
   DBMS_OUTPUT.PUT_LINE('LOC : ' || dept_rec.loc);
END;
/

레코드를 사용한 INSERT

레코드를 사용할 테이블 DEPT_RECORD생성

CREATE TABLE DEPT_RECORD
AS SELECT * FROM DEPT;

SELECT * FROM DEPT_RECORD;

INSERT문에 레코드를 사용하면 VALUES절에 레코드 이름만 명시해도 됨

선언한 레코드와 INSERT대상이 되는 테이블의 데이터 갯수,자료형,순서를 맞추어야 함

DECLARE
   TYPE REC_DEPT IS RECORD(
      deptno NUMBER(2) NOT NULL := 99,
      dname DEPT.DNAME%TYPE,
      loc DEPT.LOC%TYPE
   );
   dept_rec REC_DEPT;
BEGIN
   dept_rec.deptno := 99;
   dept_rec.dname := 'DATABASE';
   dept_rec.loc := 'SEOUL';

   INSERT INTO DEPT_RECORD
   VALUES dept_rec;
END;
/

레코드를 사용한 UPDATE

SET절은ROW키워드와 함께 레코드 이름을 명시

레코드에 저장된 데이터를 사용하여 행 전체의 데이터를 바꿔줌

DECLARE
   TYPE REC_DEPT IS RECORD(
      deptno NUMBER(2) NOT NULL := 99,
      dname DEPT.DNAME%TYPE,
      loc DEPT.LOC%TYPE
   );
   dept_rec REC_DEPT;
BEGIN
   dept_rec.deptno := 50;
   dept_rec.dname := 'DB';
   dept_rec.loc := 'SEOUL';

   UPDATE DEPT_RECORD
      SET ROW = dept_rec
    WHERE DEPTNO = 99;
END;
/

SELECT * FROM DEPT_RECORD;

레코드를 포함하는 레코드

레코드에 포함된 변수의 자료형을 지정할 때 다른 레코드를 지정할 수도 있음

레코드 역시 자료형이기 떄문

중첩 레코드 : 레코드 안에 또 다른 레코드를 포함한 형태,변수에 레코드 형을 적용했으므로 두 개의 마침표(.)로 값을 사용

DECLARE
   TYPE REC_DEPT IS RECORD(
      deptno DEPT.DEPTNO%TYPE,
      dname DEPT.DNAME%TYPE,
      loc DEPT.LOC%TYPE
   );
   TYPE REC_EMP IS RECORD(
      empno EMP.EMPNO%TYPE,
      ename EMP.ENAME%TYPE,
      dinfo REC_DEPT
   );
   emp_rec REC_EMP;
BEGIN
   SELECT E.EMPNO, E.ENAME, D.DEPTNO, D.DNAME, D.LOC
     INTO emp_rec.empno, 
			    emp_rec.ename,
          emp_rec.dinfo.deptno,
          emp_rec.dinfo.dname,
          emp_rec.dinfo.loc
     FROM EMP E, DEPT D
    WHERE E.DEPTNO = D.DEPTNO
      AND E.EMPNO = 7788;

   DBMS_OUTPUT.PUT_LINE('EMPNO : ' || emp_rec.empno);
   DBMS_OUTPUT.PUT_LINE('ENAME : ' || emp_rec.ename);
   DBMS_OUTPUT.PUT_LINE('DEPTNO : ' || emp_rec.dinfo.deptno);
   DBMS_OUTPUT.PUT_LINE('DNAME : ' || emp_rec.dinfo.dname);
   DBMS_OUTPUT.PUT_LINE('LOC : ' || emp_rec.dinfo.loc);
END;
/

17-2 자료형이 같은 여러 데이터를 저장하는 컬렉션

컬렉션 : 특정 자료형의 데이터를 여러 개 저장하는 복합 자료형

여러 종류(여러 타입)의 데이터를 하나로 묶어 사용하는 레코드를 테이블의 한 행처럼 사용한다면,

컬렉션은 열 또는 테이블과 같은 형태로 사용할 수 있음

PL/SQL에서 사용할 수 있는 컬렉션

- 연관 배열(ASSOCIATIVE ARRAY OR INDEX BY TABLE)
- 중첩 테이블(NESTED TABLE)
- VARRAY(VARIABLE-SIZE ARRAY)

연관 배열

연관 배열 : 인덱스라고 불리는 키,값으로 구성되는 컬렉션

중복 되지 않은 유일한 키를 통해 값을 저장하고 불러오는 방식을 사용

연관 배열을 정의할 때 자료형이 TABLE인 변수를 다음과 같이 작성

TYPE 연관 배열 이름 IS TABLE 자료형 [NOT NULL]    --1
INDEX BY 인덱스형;     --2
  1. 연관 배열 열에 사용할 자료형에는 VARCHAR2,DATE,NUMBER와 같은 단일 자료형을 지정할 수 있으며 %TYPE,%ROWTYPE같은 참조 자료형도 사용할 수 있음
  2. NOT NULL 옵션을 사용할 수 있으며 생략 가능
  3. 키로 사용할 인덱스의 자료형을 지정
  4. BINARY_INTEGER,PLS_INTEGER 같은 정수 또는 VARCHAR2같은 문자 자료형도 사용

정의한 연관배열은 레코드와 마찬가지로 특정 변수의 자료형으로 사용 가능

DECLARE
	--인덱스값을 정수로 사용하여 값을 저장하는 연관 배열 정의
   TYPE ITAB_EX IS TABLE OF VARCHAR2(20)
      INDEX BY PLS_INTEGER;

   text_arr ITAB_EX;

BEGIN
   text_arr(1) := '1st data';
   text_arr(2) := '2nd data';
   text_arr(3) := '3rd data';
   text_arr(4) := '4th data';

   DBMS_OUTPUT.PUT_LINE('text_arr(1) : ' || text_arr(1));
   DBMS_OUTPUT.PUT_LINE('text_arr(2) : ' || text_arr(2));
   DBMS_OUTPUT.PUT_LINE('text_arr(3) : ' || text_arr(3));
   DBMS_OUTPUT.PUT_LINE('text_arr(4) : ' || text_arr(4));
END;
/

레코드를 활용한 연관 배열

연관 배열의 자료형으로 레코드 사용 가능

이 경우 다양한 자료형을 포함한 레코드를 여러 개 사용할 수 있으므로 마치 테이블과 같은 데이터 사용과 저장이 가능

DECLARE
   TYPE REC_DEPT IS RECORD(
      deptno DEPT.DEPTNO%TYPE,
      dname DEPT.DNAME%TYPE
   );

   TYPE ITAB_DEPT IS TABLE OF REC_DEPT
      INDEX BY PLS_INTEGER;

   dept_arr ITAB_DEPT;
   idx PLS_INTEGER := -1;

BEGIN
   FOR i IN (SELECT DEPTNO, DNAME FROM DEPT) LOOP
      idx := idx + 1;
      dept_arr(idx).deptno := i.DEPTNO;
      dept_arr(idx).dname := i.DNAME;

      DBMS_OUTPUT.PUT_LINE(
         dept_arr(idx).deptno || ' : ' || dept_arr(idx).dname);
   END LOOP;
END;
/

특정 테이블의 전체 열과 같은 구성을 가진 연관 배열을 제작한다면 다음과 같이 %ROWTYPE을 사용하는 것이 레코드를 정의하는 것보다 간편

DECLARE
   TYPE ITAB_DEPT IS TABLE OF DEPT%ROWTYPE
      INDEX BY PLS_INTEGER;

   dept_arr ITAB_DEPT;
   idx PLS_INTEGER := 0;

BEGIN
   FOR i IN(SELECT * FROM DEPT) LOOP
      idx := idx + 1;
      dept_arr(idx).deptno := i.DEPTNO;
      dept_arr(idx).dname := i.DNAME;
      dept_arr(idx).loc := i.LOC;

      DBMS_OUTPUT.PUT_LINE(
      dept_arr(idx).deptno || ' : ' ||
      dept_arr(idx).dname || ' : ' ||
      dept_arr(idx).loc);
   END LOOP;
END;
/
10 : ACCOUNTING
20 : RESEARCH
30 : SALES
40 : OPERATIONS

컬렉션 메서드

컬렉션 메서드는 컬렉션과 관련된 다양한 정보 조회 기능을 제공

컬렉션 내의 데이터 삭제나 컬렉션 크기 조절을 위한 특정 조작도 가능

메서드 설  명

EXISTS(n) 컬렉션에서  n 인덱스의 데이터 존재 여부를  true / false 로 반환
COUNT 컬렉션에 포함되어 있는 요소 개수를 반환
LIMIT 현재 컬렉션의 최대 크기 반환최대 크기가 없으면  NULL 반환
FIRST 컬렉션의 첫 번째 인덱스 번호 반환
LAST 컬렉션의 마지막 인덱스 번호 반환
PRIOR(n) 컬렉션에서  n 인덱스 바로 앞 인덱스 값을 반환대상 인덱스 값이 존재하지 않으면  NULL 을 반환
NEXT(n) 컬렉션에서 n인덱스 바로 다음 인덱스 값을 반환대상 인덱스 값이 존재하지 않는다면  NULL 을 반환
DELETE 컬렉션에 저장된 요소를 지우는데 사용-  DELETE  : 컬렉션에 저장되어 있는 모든 요소 삭제-  DELETE(n)  :  n 인덱스의 컬렉션 요소를 삭제-  DELETE(n, m) :  n 인덱스 ~  m 인덱스 까지 요소를 삭제
EXTEND 컬렉션 크기를 증가시킴. 연관 배열을 제외한 중첩 테이블과  VARRAY 에서 사용
TRIM 컬렉션 크기를 감소시킴. 연관 배열을 제외한 중첩 테이블과  VARRAY 에서 사용

컬렉션 메서드는 컬렉션 형으로 선언한 변수에 마침표(.)와 함께 작성하여 사용

DECLARE
   TYPE ITAB_EX IS TABLE OF VARCHAR2(20)
      INDEX BY PLS_INTEGER;

   text_arr ITAB_EX;

BEGIN
   text_arr(1) := '1st data';
   text_arr(2) := '2nd data';
   text_arr(3) := '3rd data';
   text_arr(50) := '50th data';

   DBMS_OUTPUT.PUT_LINE('text_arr.COUNT : ' || text_arr.COUNT);
   DBMS_OUTPUT.PUT_LINE('text_arr.FIRST : ' || text_arr.FIRST);
   DBMS_OUTPUT.PUT_LINE('text_arr.LAST : ' || text_arr.LAST);
   DBMS_OUTPUT.PUT_LINE('text_arr.PRIOR(50) : ' || text_arr.PRIOR(50));
   DBMS_OUTPUT.PUT_LINE('text_arr.NEXT(50) : ' || text_arr.NEXT(50));

END;
/
text_arr.COUNT : 4
text_arr.FIRST : 1
text_arr.LAST : 50
text_arr.PRIOR(50) : 3
text_arr.NEXT(50) : 

CHAPTER17. 레코드와 컬렉션

17-1 자료형이 다른 여러 데이터를 저장하는 레코드

레코드란?

레코드는 자료형이 각기 다른 데이터를 하나의 변수에 저장하는데 사용

TYPE 레코드이름 IS RECORD(
변수이름 자료형 NOT NULL := (또는 DEFAULT) 값 또는 값이 도출되는 여러 표현식
)

자료형에 %TYPE,%ROWTYPE지정이 가능

프로그래밍 언어의 구조체, 클래스 개념과 비슷

정의한 레코드는 기존 자료형 처럼 사용할 수 있음

레코드에 포함된 변수는 레코드 이름과 마침표(.)로 사용할 수 있음

DECLARE
   TYPE REC_DEPT IS RECORD(
      deptno NUMBER(2) NOT NULL := 99,
      dname DEPT.DNAME%TYPE,
      loc DEPT.LOC%TYPE
   );
   dept_rec REC_DEPT;    --선언한 레코드형으로 변수 선언
BEGIN
   dept_rec.deptno := 99;
   dept_rec.dname := 'DATABASE';
   dept_rec.loc := 'SEOUL';
   DBMS_OUTPUT.PUT_LINE('DEPTNO : ' || dept_rec.deptno);
   DBMS_OUTPUT.PUT_LINE('DNAME : ' || dept_rec.dname);
   DBMS_OUTPUT.PUT_LINE('LOC : ' || dept_rec.loc);
END;
/

레코드를 사용한 INSERT

레코드를 사용할 테이블 DEPT_RECORD생성

CREATE TABLE DEPT_RECORD
AS SELECT * FROM DEPT;

SELECT * FROM DEPT_RECORD;

INSERT문에 레코드를 사용하면 VALUES절에 레코드 이름만 명시해도 됨

선언한 레코드와 INSERT대상이 되는 테이블의 데이터 갯수,자료형,순서를 맞추어야 함

DECLARE
   TYPE REC_DEPT IS RECORD(
      deptno NUMBER(2) NOT NULL := 99,
      dname DEPT.DNAME%TYPE,
      loc DEPT.LOC%TYPE
   );
   dept_rec REC_DEPT;
BEGIN
   dept_rec.deptno := 99;
   dept_rec.dname := 'DATABASE';
   dept_rec.loc := 'SEOUL';

   INSERT INTO DEPT_RECORD
   VALUES dept_rec;
END;
/

레코드를 사용한 UPDATE

SET절은ROW키워드와 함께 레코드 이름을 명시

레코드에 저장된 데이터를 사용하여 행 전체의 데이터를 바꿔줌

DECLARE
   TYPE REC_DEPT IS RECORD(
      deptno NUMBER(2) NOT NULL := 99,
      dname DEPT.DNAME%TYPE,
      loc DEPT.LOC%TYPE
   );
   dept_rec REC_DEPT;
BEGIN
   dept_rec.deptno := 50;
   dept_rec.dname := 'DB';
   dept_rec.loc := 'SEOUL';

   UPDATE DEPT_RECORD
      SET ROW = dept_rec
    WHERE DEPTNO = 99;
END;
/

SELECT * FROM DEPT_RECORD;

레코드를 포함하는 레코드

레코드에 포함된 변수의 자료형을 지정할 때 다른 레코드를 지정할 수도 있음

레코드 역시 자료형이기 떄문

중첩 레코드 : 레코드 안에 또 다른 레코드를 포함한 형태,변수에 레코드 형을 적용했으므로 두 개의 마침표(.)로 값을 사용

DECLARE
   TYPE REC_DEPT IS RECORD(
      deptno DEPT.DEPTNO%TYPE,
      dname DEPT.DNAME%TYPE,
      loc DEPT.LOC%TYPE
   );
   TYPE REC_EMP IS RECORD(
      empno EMP.EMPNO%TYPE,
      ename EMP.ENAME%TYPE,
      dinfo REC_DEPT
   );
   emp_rec REC_EMP;
BEGIN
   SELECT E.EMPNO, E.ENAME, D.DEPTNO, D.DNAME, D.LOC
     INTO emp_rec.empno, 
			    emp_rec.ename,
          emp_rec.dinfo.deptno,
          emp_rec.dinfo.dname,
          emp_rec.dinfo.loc
     FROM EMP E, DEPT D
    WHERE E.DEPTNO = D.DEPTNO
      AND E.EMPNO = 7788;

   DBMS_OUTPUT.PUT_LINE('EMPNO : ' || emp_rec.empno);
   DBMS_OUTPUT.PUT_LINE('ENAME : ' || emp_rec.ename);
   DBMS_OUTPUT.PUT_LINE('DEPTNO : ' || emp_rec.dinfo.deptno);
   DBMS_OUTPUT.PUT_LINE('DNAME : ' || emp_rec.dinfo.dname);
   DBMS_OUTPUT.PUT_LINE('LOC : ' || emp_rec.dinfo.loc);
END;
/

17-2 자료형이 같은 여러 데이터를 저장하는 컬렉션

컬렉션 : 특정 자료형의 데이터를 여러 개 저장하는 복합 자료형

여러 종류(여러 타입)의 데이터를 하나로 묶어 사용하는 레코드를 테이블의 한 행처럼 사용한다면,

컬렉션은 열 또는 테이블과 같은 형태로 사용할 수 있음

PL/SQL에서 사용할 수 있는 컬렉션

- 연관 배열(ASSOCIATIVE ARRAY OR INDEX BY TABLE)
- 중첩 테이블(NESTED TABLE)
- VARRAY(VARIABLE-SIZE ARRAY)

연관 배열

연관 배열 : 인덱스라고 불리는 키,값으로 구성되는 컬렉션

중복 되지 않은 유일한 키를 통해 값을 저장하고 불러오는 방식을 사용

연관 배열을 정의할 때 자료형이 TABLE인 변수를 다음과 같이 작성

TYPE 연관 배열 이름 IS TABLE 자료형 [NOT NULL]    --1
INDEX BY 인덱스형;     --2
  1. 연관 배열 열에 사용할 자료형에는 VARCHAR2,DATE,NUMBER와 같은 단일 자료형을 지정할 수 있으며 %TYPE,%ROWTYPE같은 참조 자료형도 사용할 수 있음
  2. NOT NULL 옵션을 사용할 수 있으며 생략 가능
  3. 키로 사용할 인덱스의 자료형을 지정
  4. BINARY_INTEGER,PLS_INTEGER 같은 정수 또는 VARCHAR2같은 문자 자료형도 사용

정의한 연관배열은 레코드와 마찬가지로 특정 변수의 자료형으로 사용 가능

DECLARE
	--인덱스값을 정수로 사용하여 값을 저장하는 연관 배열 정의
   TYPE ITAB_EX IS TABLE OF VARCHAR2(20)
      INDEX BY PLS_INTEGER;

   text_arr ITAB_EX;

BEGIN
   text_arr(1) := '1st data';
   text_arr(2) := '2nd data';
   text_arr(3) := '3rd data';
   text_arr(4) := '4th data';

   DBMS_OUTPUT.PUT_LINE('text_arr(1) : ' || text_arr(1));
   DBMS_OUTPUT.PUT_LINE('text_arr(2) : ' || text_arr(2));
   DBMS_OUTPUT.PUT_LINE('text_arr(3) : ' || text_arr(3));
   DBMS_OUTPUT.PUT_LINE('text_arr(4) : ' || text_arr(4));
END;
/

레코드를 활용한 연관 배열

연관 배열의 자료형으로 레코드 사용 가능

이 경우 다양한 자료형을 포함한 레코드를 여러 개 사용할 수 있으므로 마치 테이블과 같은 데이터 사용과 저장이 가능

DECLARE
   TYPE REC_DEPT IS RECORD(
      deptno DEPT.DEPTNO%TYPE,
      dname DEPT.DNAME%TYPE
   );

   TYPE ITAB_DEPT IS TABLE OF REC_DEPT
      INDEX BY PLS_INTEGER;

   dept_arr ITAB_DEPT;
   idx PLS_INTEGER := -1;

BEGIN
   FOR i IN (SELECT DEPTNO, DNAME FROM DEPT) LOOP
      idx := idx + 1;
      dept_arr(idx).deptno := i.DEPTNO;
      dept_arr(idx).dname := i.DNAME;

      DBMS_OUTPUT.PUT_LINE(
         dept_arr(idx).deptno || ' : ' || dept_arr(idx).dname);
   END LOOP;
END;
/

특정 테이블의 전체 열과 같은 구성을 가진 연관 배열을 제작한다면 다음과 같이 %ROWTYPE을 사용하는 것이 레코드를 정의하는 것보다 간편

DECLARE
   TYPE ITAB_DEPT IS TABLE OF DEPT%ROWTYPE
      INDEX BY PLS_INTEGER;

   dept_arr ITAB_DEPT;
   idx PLS_INTEGER := 0;

BEGIN
   FOR i IN(SELECT * FROM DEPT) LOOP
      idx := idx + 1;
      dept_arr(idx).deptno := i.DEPTNO;
      dept_arr(idx).dname := i.DNAME;
      dept_arr(idx).loc := i.LOC;

      DBMS_OUTPUT.PUT_LINE(
      dept_arr(idx).deptno || ' : ' ||
      dept_arr(idx).dname || ' : ' ||
      dept_arr(idx).loc);
   END LOOP;
END;
/
10 : ACCOUNTING
20 : RESEARCH
30 : SALES
40 : OPERATIONS

컬렉션 메서드

컬렉션 메서드는 컬렉션과 관련된 다양한 정보 조회 기능을 제공

컬렉션 내의 데이터 삭제나 컬렉션 크기 조절을 위한 특정 조작도 가능

메서드 설  명

EXISTS(n) 컬렉션에서  n 인덱스의 데이터 존재 여부를  true / false 로 반환
COUNT 컬렉션에 포함되어 있는 요소 개수를 반환
LIMIT 현재 컬렉션의 최대 크기 반환최대 크기가 없으면  NULL 반환
FIRST 컬렉션의 첫 번째 인덱스 번호 반환
LAST 컬렉션의 마지막 인덱스 번호 반환
PRIOR(n) 컬렉션에서  n 인덱스 바로 앞 인덱스 값을 반환대상 인덱스 값이 존재하지 않으면  NULL 을 반환
NEXT(n) 컬렉션에서 n인덱스 바로 다음 인덱스 값을 반환대상 인덱스 값이 존재하지 않는다면  NULL 을 반환
DELETE 컬렉션에 저장된 요소를 지우는데 사용-  DELETE  : 컬렉션에 저장되어 있는 모든 요소 삭제-  DELETE(n)  :  n 인덱스의 컬렉션 요소를 삭제-  DELETE(n, m) :  n 인덱스 ~  m 인덱스 까지 요소를 삭제
EXTEND 컬렉션 크기를 증가시킴. 연관 배열을 제외한 중첩 테이블과  VARRAY 에서 사용
TRIM 컬렉션 크기를 감소시킴. 연관 배열을 제외한 중첩 테이블과  VARRAY 에서 사용

컬렉션 메서드는 컬렉션 형으로 선언한 변수에 마침표(.)와 함께 작성하여 사용

DECLARE
   TYPE ITAB_EX IS TABLE OF VARCHAR2(20)
      INDEX BY PLS_INTEGER;

   text_arr ITAB_EX;

BEGIN
   text_arr(1) := '1st data';
   text_arr(2) := '2nd data';
   text_arr(3) := '3rd data';
   text_arr(50) := '50th data';

   DBMS_OUTPUT.PUT_LINE('text_arr.COUNT : ' || text_arr.COUNT);
   DBMS_OUTPUT.PUT_LINE('text_arr.FIRST : ' || text_arr.FIRST);
   DBMS_OUTPUT.PUT_LINE('text_arr.LAST : ' || text_arr.LAST);
   DBMS_OUTPUT.PUT_LINE('text_arr.PRIOR(50) : ' || text_arr.PRIOR(50));
   DBMS_OUTPUT.PUT_LINE('text_arr.NEXT(50) : ' || text_arr.NEXT(50));

END;
/
text_arr.COUNT : 4
text_arr.FIRST : 1
text_arr.LAST : 50
text_arr.PRIOR(50) : 3
text_arr.NEXT(50) :