CHAPTER 17. 레코드와 컬렉션-DO IT!오라클로 배우는 데이터베이스 입문
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
- 연관 배열 열에 사용할 자료형에는 VARCHAR2,DATE,NUMBER와 같은 단일 자료형을 지정할 수 있으며 %TYPE,%ROWTYPE같은 참조 자료형도 사용할 수 있음
- NOT NULL 옵션을 사용할 수 있으며 생략 가능
- 키로 사용할 인덱스의 자료형을 지정
- 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
- 연관 배열 열에 사용할 자료형에는 VARCHAR2,DATE,NUMBER와 같은 단일 자료형을 지정할 수 있으며 %TYPE,%ROWTYPE같은 참조 자료형도 사용할 수 있음
- NOT NULL 옵션을 사용할 수 있으며 생략 가능
- 키로 사용할 인덱스의 자료형을 지정
- 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
- 연관 배열 열에 사용할 자료형에는 VARCHAR2,DATE,NUMBER와 같은 단일 자료형을 지정할 수 있으며 %TYPE,%ROWTYPE같은 참조 자료형도 사용할 수 있음
- NOT NULL 옵션을 사용할 수 있으며 생략 가능
- 키로 사용할 인덱스의 자료형을 지정
- 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) :