일기

24.07.08(월) index by table연관배열/ 행레벨INSERT/행레벨UPDATE

Boggi 2024. 7. 10. 19:44
반응형

2.연관배열(Associative array, index by table)
- 데이터를 저장하는데 인덱스가 쓰이는구나 
- 연관 배열은 2개의 열을 포함하는 배열 구조이다.
- 요소번호: 정수(보통 pls_integer), 문자열 데이터 유형(varchar2)의 primary key(방번호)가 필요.(요소번호)
- 값: 스칼라 또는 레코드 데이터 유형의 열이 필요.
DECLARE
    TYPE date_type IS TABLE OF date INDEX BY pls_integer;
    v_tab date_type;
    
■조합데이터 유형
-레코드: 서로 다른 데이터 유형의 값을 저장
-배열: 동일한 데이터 유형의 값을 저장(1차원 배열) 단일값을 쌓아놓고 조작.(???)
-index by table(연관배열)
-nested table(중첩테이블)
-varray
: 레코드 타입을 응용해서 2차원 배열을 생성할 수 있다.
레코드 타입의 변수: 서로 다른 스칼라데이터 타입의 변수를 모아서 만들어진 변수

1. 레코드(record) --레코드 타입 선언하기

TYPE 레코드이름 IS RECORD
( 필드1 데이터타입, ---필드
  필드2 데이터타입,
  필드3 데이터타입,
  필드4 데이터타입); -->변수 선언

변수 레코드타입이름; --> 레코드 타입을 변수로 지정
레코드 사용할 때는? 변수명.필드명
-- 각각의 필드가 모여서 하나의 레코드가 만들어짐. 스칼라 타입이 모여서 레코드 타입이 만들어진다.
-- 하나의 필드 안에 레코드 형식이 들어갈 수도 있어

레코드타입은 왜 쓰니?
- SELECT *할 때(데이터를 모두 불러오기 위해서)
(근데 레코드를 쓰려면 필드 구성을 해야하는데 번거로우니 쉽게 할 수 있는 게 있어!)

■%rowtype 속성
- 테이블 또는 뷰에서 모든 컬럼 및 데이터 유형을 가지고 온다.
장점: 테이블의 컬럼의 구조를 알 필요가 없어. 실제 런타임에 정보를 가져온다.
언제 %rowtype 속성을 써?
1. SELECT * 문 사용할 때
2. 행레벨의 INSERT문
3. 행레벨의 UPDATE문

--INSERT하기 만약 레코드변수의 모습과 테이블 컬럼의 모습이 다르면 하나씩 다 써줘야 해.
DECLARE
    v_rec hr.employees%rowtype;
BEGIN
    SELECT *
    INTO v_rec      --115번 사원에 대한 모든 정보를 v_rec에 패치시켜라
    FROM hr.employees
    WHERE employee_id = 115; --퇴사사원이라 가정하자
    
    INSERT INTO hr.retired_emp(empno, ename, job, mgr, hiredate, leavedate, sal, comm, deptno)
    VALUES(v_rec.employee_id, v_rec.first_name, v_rec.job_id, v_rec.manager_id, v_rec.hire_date, sysdate, v_rec.salary, v_rec.commission_pct, v_rec.department_id);
END;
/
이거를 
-- 행레벨의 INSERT문
-- v_rec 구조와 hr.retired_emp여기의 구조가 같다면 INSERT를 이렇게 해도 된다.
DECLARE
    v_rec hr.retired_emp%rowtype;
BEGIN
    SELECT employee_id, first_name, job_id, manager_id, hire_date, sysdate, salary, commission_pct, department_id
    INTO v_rec      
    FROM hr.employees
    WHERE employee_id = 115; --퇴사사원이라 가정하자
    /*행레벨 INSERT*/
    INSERT INTO hr.retired_emp
    VALUES v_rec;
END;
/

--UPDATE 해보자!
DECLARE
    v_rec hr.retired_emp%rowtype;
BEGIN
    SELECT *
    INTO v_rec
    FROM hr.retired_emp
    WHERE empno = 115;
    
    v_rec.ename := lower(v_rec.ename);
    v_rec.leavedate := to_date('2024-06-15','yyyy-mm-dd');
    v_rec.comm := 1.13;
    
    UPDATE hr.retired_emp
    SET ename = v_rec.ename, leavedate =  v_rec.leavedate, comm=v_rec.comm
    WHERE empno = 115;
END;
/

--행레벨 UPDATE
DECLARE
    v_rec hr.retired_emp%rowtype;
BEGIN
    SELECT *
    INTO v_rec
    FROM hr.retired_emp
    WHERE empno = 115;
    
    v_rec.ename := lower(v_rec.ename);
    v_rec.leavedate := to_date('2024-06-15','yyyy-mm-dd');
    v_rec.comm := 1.13;
    /*행레벨 UPDATE*/
    UPDATE hr.retired_emp
    SET ROW = v_rec
    WHERE empno = 115;
END;
/

2.배열
연관배열(Associative array, index by table)
- 데이터를 저장하는 데 인덱스가 쓰임
- 연관 배열은 2개의 열을 포함하는 배열 구조
- 2개의 열은 요소번호와 값이 들어있음
요소번호: 정수(보통 pls_integer 사이즈 -2G~2G), 문자형 데이터 유형(varchar2)의 primary key(방번호)가 필요
값: 스칼라 또는 레코드 유형의 열이 필요
--배열변수를 쓰는 이유?
 실행계획을 쉐어링하기 위해서! 

TYPE 배열타입이름 IS TABLE OF 값(데이터 타입) INDEX BY 요소번호(방번호);

DECLARE
    TYPE tab_char_type IS TABLE OF varchar2(10) INDEX BY pls_integer;
    v_city tab_char_type;

-메소드
v_city.count: 배열에 저장된 요소의 수를 세어줌.(몇개 들어있니)
v_city.first : 가장 작은방 번호
v_city.last : 가장 큰 방 번호
v_city.next(1) : 다음번호(배열의 번호에 갭이 있을 때 사용)
v_city.prior(3) : 이전번호(배열의 번호에 갭이 있을 때 사용)

v_city.exists(i) : n번 요소가 존재하면 TRUE 아니면 FALSE 반환

 DECLARE
    TYPE tab_char_type IS TABLE OF varchar2(10) INDEX BY pls_integer;
    v_city  tab_char_type; 

--데이터 삭제하기
v_city.delete(n) : 배열의 n번 요소 삭제하기
v_city.delete(m,n) : 배열의 m번부터 n번 범위의 요소 삭제
v_city.delete; : 배열의 모든 요소 삭제