VIEW
뷰란?
- 사용자에게 접근이 허락 된 데이터만 제한적으로 제
- 하나 이상의 테이블로부터 유도 된 가상 테이블
- 뷰에 대한 질의 실행시 정의된 테이블로 대체되어 실행
- 임시 작업을 위한 용도로 활용되고 사용상의 편의성을 최대화함
특징
- 테이블에서 유도되었기 때문에 구조가 같다.
- 가상 테이블이라 물리적으로 구현되지 않아있다.
- 데이터의 논리적 독립성 제공
- 뷰로 필요한 데이터만 처리하므로 관리 용이
- 여러 테이블을 조인하여 뷰 생성 가능
- 뷰에 나타나지 않은 데이터를 안전하게 보호
- 테이블의 기본키를 포함하여 뷰를 구성하면 삽입, 삭젝, 갱신 가능
장점 | 단점 |
- 논리적 데이터 독립성 제공 - 동일 데이터에 대해 동시에 여러 사용자 요구 지원 - 사용자의 데이터 관리 편의성 제공 - 접근 제어를 통한 보안 제공 |
- 독립적 인덱스 생성 불가 - 뷰의 정의 변경 불가 - 삽입, 수정, 삭제 연산에 제약 |
[ 하나의 테이블에서 파생한 뷰 ]
CREATE(또는 REPLACE) VIEW (뷰 이름) AS -- CREATE 대신 REPLACE를 사용하면 같은 이름의 기존 뷰를 무시하고 대체
(
SELECT COL1, COL2, ...
FROM (테이블명)
WHERE (조건) -- WHERE, JOIN 등 테이블을 조회하는 방식, 조건 등을 일종의 함수처럼 정의하면 됨.
);
-- 위처럼 한 번 생성해두면, 아래처럼 조회 가능
SELECT * FROM (뷰 이름);
[ 여러 테이블에서 파생한 뷰 ]
여러 테이블에서 파생되었기 때문에 각 테이블에 별칭을 지어주고 어떤 테이블의 어떤 컬럼인지 명시해주어야 한다.
CREATE VIEW (생성할 뷰 이름) AS
(
SELECT COL1, COL2, ...
FROM (테이블1) A, (테이블2) B, ...
(WHERE, JOIN 등 사용 가능)
);
뷰의 종류
- 단순 뷰 : 첫번째 예시처럼 단순히 하나의 테이블에서 생성된 뷰
- 복합 뷰 : 두번째 예시처럼 하나 이상의 테이블에서 생성된 뷰
- 인라인 뷰 : SELECT문에서 FROM절에 기술된 SELECT문
[ 예제 ]
CREATE OR REPLACE VIEW new_imployees_view AS
SELECT employee_id, first_name, last_name, email, hire_job,job_id
FROM employees
WHERER employee_id >206;
employees 테이블에서 employee_id가 206보다 큰 정보들만를 담아 뷰를 만들었다.
VIEW는 추후에 INSERT도 가능하다.
INSERT INTO new_imployess_view VALUES(207,'Suan','Lee','suan','23/01/01','IT_PROG');
우린 방금 employess테이블로 만든 new_imployee_view라는 뷰에 새로운 값을 INSERT했는데 employees테이블을 확인해보면 뷰에 넣은 값이 들어간걸 확인할 수 있다.
여기서 주의 해야할 점은 혹시 뷰에서 값을 넣었는데 기존 테이블에서 not null제약이 걸린 컬럼을 무시하고 뷰에 INSERT를 한다면 제약이 걸려 삽입이 되지 않는다.
삽입까지 해봤으니 삭제도 해보자.
DELETE FROM new_imployee_view where imployee_id = 207;
방금 뷰에 새로 넣은 값을 삭제하면 정상 작동이 되고 역시 마찬가지로 employees테이블에서도 삭제 된 모습이다.
마지막으로 뷰 삭제를 해보자. 테이블을 삭제하는 방식과 똑같다.
DROP VIEW new_imployee_view;
읽기 전용 VIEW
읽기전용 VIEW는 말 그대로 읽기만 가능하게 만들어놓은 뷰이다.
[예제]
CREATE OR REPLACE VIEW salary_order_view AS
SELECT first_name, last_name, job_id, salary
FROM employees
ORDER BY salary DESC
WITH READ ONLY;
읽기 전용 뷰를 생성하는건 맨 마지막에 WITH READ ONLY를 추가해주면 된다.
CREATE METERIALIZED VIEW
- 구체화 된 뷰
이번에 만들어 볼 VIEW는 조금 다르다. 이전까지 만들었던 뷰들은 모두 실제로 물리적으로 존재하지 않는 가상의 테이블이였지만 이번에 METERIALIZED VIEW는 실제로 구체화 되어 만들어지는 VIEW가 된다.
물리적으로 존재한다는 것은 Data가 일정 공간을 차지하게 된다.
- 사용하는 이유
MView는 어떤 결과를 뽑아 내는 쿼리가 너무나도 빈번히 사용 될 경우, Query 실행 시간의 수행속도 향상을위하여 , 여러 가지의 Aggregate View를 두어, 미리 비용이 많이 드는 조인이나, Aggregate Operation 을 처리하여야 하는 SQL을 위해, 데이터베이스의 한 테이블로 저장 하며, 그 테이블을 조회 하도록 하는 것 입니다.
자주사용되는 View의 결과를 디스크에 저장해서 Query 속도를 향상시키는 개념 입니다.
CREATE MATERIALIZED VIEW 뷰이름
[ BUILD {IMMEDIATE | DEFFERED}
REFRESH {ON COMMIT | ON DEMAND} {FAST | COMPLETE | FORCE | NAVER}
ENABLE QUERY REWRITE ]
AS
SELECT 질의;
- BUILD IMMEDIATE : 구체화 된 뷰 생성 후, 동시에 구체화 된 내부에 데이터가 채워짐
- BUILD DEFFERED : 뷰 내부에 구조는 생기지만 데이터는 나중에 채워짐
- REFRESH ON COMMIT : 원본 테이블에 COMMIT이 발생될 때마다 뷰의 내용이 변경
- REFRESH ON DEMAND : 직접 DBMS_MVIEW 패키지를 실행해서 구체화된 뷰의 내용을 변경
- FAST, FORCE : 원본 테이블에 변경된 데이터만 구체화 된 뷰에 적용
- COMPLETE : 원본 테이블이 변경되면 전체를 구체화 된 뷰에 적용
- NAVER : 원본 테이블이 변경되어도 구체화된 뷰에는 적용 안함
[ 예제 ]
CREATE MATERIALIZED VIEW country_location_view
BUILD DEFERRED
AS
SELECT C.country_name, L.state_province, L.street_address
FROM countries C, locations L
WHERE C.country_id = L.country_id;
일반 유저의 권한으로는 MATERIAIZED VIEW는 생성할 수 없다.
해당 뷰를 생성하기 위해서는 현재 유저에게 Query Rewrite, Create Materialized view권한을 부여해야 한다.
생성을 하고 SELECT를 해보면 아무런 값이 들어잇지 않은 모습을 볼 수 있다. 이유는 처음에 해당 VIEW를 생성 할 때 옵션으로 BUILD DEFERRED를 주었기 때문에 아직 데이터가 들어있지 않은 것이다.
이제 데이터를 넣고싶다면
EXECUTE DMBS_MVIEW.REFRESH(LIST=>'country_location_view');
이렇게 데이터를 채워 넣어줄 수 있다. 다시 SELECT를 사용해보면 값이 보이는걸 확인 할 수 있다.
[ 예제2 ]
CREATE MATERIALIZED VIEW country_location_view
BUILD IMMEDIATE
REFRESH ON DEMAND COMPLETE
AS
SELECT C.country_name, L.state_province, L.street_address
FROM countries C, locations L
WHERE C.country_id = L.country_id;
이번엔 옵션을 바꿔서 생성해 보았다. 해당 옵션에 대해 설명을 해보자면 MATERIALIZED VIEW를 생성함과 동시에 데이터가 채워지게 되며 원본 테이블의 값이 변경이 되어도 해당 뷰에는 MVIEW패키지를 이용해서 업데이트가 되게 햇으며, 업데이트 될 때 변경된 데이터만 바뀌는게 아니라 전체가 뷰에 새로 적용이 된다.
INSERT INTO countries VALUES ('KR','Replubic of Korea',3);
INSERT INTO location VALUES (3300,'1 Cheonwadae-ro',03048,'Seoul','Jongno-gu','KR');
생성한 MAATERIALIZED VIEW에 조건에 맞게 두 테이블에 새로운 값을 넣어주고 다시 VIEW를 SELECT 해보면 변화가 없는걸 알 수 있다. REFRESH ON DEMAND 옵션으로 MVIEW패키지를 이용해야 뷰의 내용이 바뀌게 된다.
EXECUTE DBMS_MVIEW.REFRESH(LIST=>'country_location_view');
변경이 될 때는 COMPLETE 옵션으로 변경된 데이터만 바뀌는게 아니라 전체의 데이터가 바뀌게 된다.
[ 실습 ]
1. employees 테이블을 manager_id와 employee_id를 기준으로 자체 조인 한 뒤 department_id와 직원의 first_name과 last_name을 결합하고 관리자의 first_name과 last_name을 결합한 뒤에 department_id를 기준으로 정렬하여 employee_manager_view이름의 읽기 전용 뷰 생성
CREATE OR REPLACE employee_manager_view
AS
SELETC E.department_id,
E.first_name | '' | E.last_name employee,
M.first_name | '' | M.last_name manager
FROM employees E, employees M
WHERER E.manager_id = M.employee_id
ORDER BY e.department_id
WITH READ ONLY;
2. employees, departments, jobs, locations 테이블을 조인하여 first_name, last_name, department_name, job_title, city를 보여주는 구체화 된 뷰를 내부의 데이터를 채우고 요청시 변경된 내용의 뷰에 반영하도록 생성
CREATE METERIALIZED VIEW company_view
BUILD IMMEDIATE
REFRESH ON DEMAND COMPLETE
AS
SELECT E.first_name, E.last_name, D.departments_name, J.job_title, L.city
FROM employees E, departments D, jobs J, locations L
WHERE E.departments_id = D.departments_id
AND E.job = J.job_id
AND D.location_id = L.location_id;