VIEW(뷰)
- SELECT 쿼리문을 저장한 객체이다.
- 실질적인 데이터를 저장하고 있지 않은 논리적인 테이블
- 테이블을 사용하는 것과 동일하게 사용 가능
- 1) 복잡한 SELECT문을 다시 작성할 필요가 없음
- 2) 민감한 데이터를 숨길 수 있음
CREATE [OR REPLACE] VIEW 뷰이름 AS 서브쿼리
사번, 이름, 직급명, 부서명, 근무지역을 조회하고, 그 결과를 V_RESULT_EMP라는 뷰를 생성해서 저장하세요
CREATE OR REPLACE VIEW V_RESULT_EMP
AS
SELECT E.EMP_ID
, E.EMP_NAME
, J.JOB_NAME
, D.DPET_TITLE
, L.LOCAL_NAME
FROM EMPLOYEE E
LEFT JOIN JOB J ON(E.JOB_CODE = J.JOB_CODE)
LEFT JOIN DEPARTMENT D ON(D.DEPT_CODE = D.DEPT_ID)
LEFT JOIN LOCATION L ON(D.LOCATION_ID = L.LOCAL_CODE);
VIEW 생성 권한 부여
<시스템 계정에서 실행>
GRANT CREATE VIEW TO C##EMPLOYEE;
사번 205 직원의 정보가 조회됨
SELECT
V.*
FROM V_RESULT_EMP V
WHERE V.EMP_ID = '205';
데이터 딕셔너리(Data Dictionary)
- 자원을 효율적으로 관리하기 위해 다양한 정보를 저장하는 시스템 테이블
- 사용자가 테이블을 생성하거나, 사용자를 변경하는 등의 작업을 할 때
데이터베이스 서버에 의해 자동으로 갱신되는 테이블
- 사용자는 데이터 딕셔너리 내용을 직접 수정하거나 삭제할 수 없음
- 원본테이블을 커스터마이징해서 보여주는 원본 테이블의 가상테이블객체(VIEW)
- 3개의 딕셔너리 뷰로 나뉨
- 1) DBA_XXX : 데이터베이스 관리자만 접근이 가능한 객체 등의 정보 조회
- 2) ALL_XXX : 자신의 계정 + 권한을 부여받은 객체의 정보 조회
- 3) USER_XXX : 자신의 계정이 소유한 객체 등에 관한 정보 조회
뷰에 대한 정보를 확인하는 데이터 딕셔너리
SELECT
UV.*
FROM USER_VIEWS UV;
뷰에 대한 별칭 부여
CREATE OR REPLACE VIEW V_EMP
(
사번
, 이름
, 부서
)
AS
SELECT E.EMP_ID
, E.EMP_NAME
, E.DEPT_CODE
FROM EMPLOYEE E;
SELECT
V.*
FROM V_EMP V;
베이스테이블의 정보가 변경되면 VIEW도 같이 변경된다.
(베이스테이블의 205사원의 이름 정중하에서 정중앙으로 변경)
UPDATE
EMPLOYEE E
SET E.EMP_NAME = '정중앙'
WHERE E.EMP_ID = '205';
베이스테이블 205사원 정중앙으로 변경됨
SELECT
E.*
FROM EMPLOYEE E
WHERE E.EMP_ID = '205';
뷰 테이블에도 똑같이 변경된 것 확인
SELECT
V.*
FROM V_RESULT_EMP V
WHERE V.EMP_ID = '205';
뷰 서브쿼리 안에 연산의 결과도 포함할 수 있다.
이 때는 반드시 별칭을 부여해서 생성해야 한다.
CREATE OR REPLACE VIEW V_EMP_JOB
(
사번
, 이름
, 직급
, 성별
, 근무년수
)
AS
SELECT E.EMP_ID
, E.EMP_NAME
, J.JOB_NAME
, DECODE(SUBSTR(E.EMP_NO, 8, 1), 1, '남', '여')
, EXTRACT(YEAR FROM SYSDATE) - EXTRACT(YEAR FROM E.HIRE_DATE)
FROM EMPLOYEE E
JOIN JOB J ON(E.JOB_CODE = J.JOB_CODE);
뷰를 통한 DML 구문 수행
CREATE OR REPLACE VIEW V_JOB
AS
SELECT J.JOB_CODE
, J.JOB_NAME
FROM JOB J;
SELECT
V.*
FROM V_JOB V;
J8 인턴이라는 새로운행 입력
INSERT
INTO V_JOB
(
JOB_CODE
, JOB_NAME
)
VALUES
(
'J8'
, '인턴'
);
베이스테이블, 뷰 테이블 모두 J8 인턴 값이 삽입된게 확인된다.
SELECT
V.*
FROM V_JOB V;
SELECT
J.*
FROM JOB J;
J8 인턴에서 알바로 변경
UPDATE
V_JOB V
SET V.JOB_NAME = '알바'
WHERE V.JOB_CODE = 'J8';
베이스테이블, 뷰 테이블 모두 J8 인턴에서 알바로 변경됨
SELECT
V.*
FROM V_JOB V;
SELECT
J.*
FROM JOB J;
DML 명령어로 조작이 불가능한 경우
- 1. 뷰 정의에 포함되지 않은 컬럼을 조작하는 경우
- 2. 뷰에 포함되지 않은 컬럼 중에 베이스가 되는 테이블 컬럼이 NOT NULL 제약조건이 지정 된 경우
- 3. 산술표현식으로 정의된 경우
- 4. JOIN을 이용해 여러 테이블을 연결한 경우
- 5. DISTINCT 포함한 경우
- 6. 그룹함수나 GROUP BY 절을 포함한 경우
위의 경우들을 위해 뷰 테이블 생성
CREATE OR REPLACE VIEW V_JOB2
AS
SELECT J.JOB_CODE
FROM JOB J;
SELECT
V.*
FROM V_JOB2 V;
1. 뷰 정의에 포함되지 않은 컬럼을 조작하는 경우
- JOB_NAME 부적합한 식별자 오류
CREATE OR REPLACE VIEW V_JOB3
AS
SELECT J.JOB_NAME
FROM JOB J;
SELECT
V.*
FROM V_JOB3 V;
INSERT
INTO V_JOB2
(
JOB_CODE
, JOB_NAME
)
VALUES
(
'J8'
, '인턴'
);
UPDATE
V_JOB2 V
SET V.JOB_NAME = '인턴'
WHERE V.JOB_CODE = 'J7';
뷰 정의에 사용된 컬럼(JOB_CODE)만 사용하므로 삽입가능
INSERT
INTO V_JOB2
(
JOB_CODE
)
VALUES
(
'J8'
);
뷰 정의에 사용된 컬럼만 사용하여 DELETE 가능
DELETE
FROM V_JOB2
WHERE JOB_CODE = 'J8';
2. 뷰에 포함되지 않은 컬럼 중에 베이스가 되는 테이블 컬럼이 NOT NULL 제약조건이 지정된 경우
CREATE OR REPLACE VIEW V_JOB3
AS
SELECT J.JOB_NAME
FROM JOB J;
SELECT
V.*
FROM V_JOB3 V;
- JOB_CODE 뷰 정의에 없어 부적합한 식별자 오류
INSERT
INTO V_JOB3
(
JOB_CODE
, JOB_NAME
)
VALUES
(
'J8'
, '인턴'
);
- JOB_CODE에는 NULL이 삽입 될 수 없어 오류
INSERT
INTO V_JOB3
(
JOB_NAME
)
VALUES
(
'인턴'
);
- 뷰에 정의 된 컬럼만을 사용한 UPDATE 수행 가능
UPDATE
V_JOB3 V
SET V.JOB_NAME = '인턴'
WHERE V.JOB_NAME = '사원';
3. 산술표현식으로 정의된 경우
CREATE OR REPLACE VIEW EMP_SAL
AS
SELECT E.EMP_ID
, E.EMP_NAME
, E.SALARY
, (E.SALARY + (E.SALARY * NVL(E.BONUS, 0))) * 12 연봉
FROM EMPLOYEE E;
- 산술표현식으로 연산된 가상 컬럼 연봉에는 INSERT 불가
INSERT
INTO EMP_SAL
(
EMP_ID
, EMP_NAME
, SALARY
, 연봉
)
VALUES
(
'800'
, '정진훈'
, 3000000
, 4000000
);
- 산술표현식으로 연산 된 가상 컬럼 연봉은 UPDATE 불가
UPDATE
EMP_SAL ES
SET ES.연봉 = 80000000
WHERE ES.EMP_ID = '200';
- DELETE의 조건으로는 사용 가능
DELETE
FROM EMP_SAL ES
WHERE ES.연봉 = 124800000;
4. JOIN을 이용해 여러 테이블을 연결한 경우
CREATE OR REPLACE VIEW V_JOINEMP
AS
SELECT E.EMP_ID
, E.EMP_NAME
, D.DEPT_TITLE
FROM EMPLOYEE E
LEFT JOIN DEPARTMENT D ON(E.DEPT_CODE = D.DEPT_ID);
- 조인 뷰에 의하여 하나 이상의 기본 테이블을 수정할 수 없습니다.
INSERT
INTO V_JOINEMP
(
EMP_ID
, EMP_NAME
, DEPT_TITLE
)
VALUES
(
888
, '조민영'
, '인사관리부'
);
- 키-보존된것이 아닌 테이블로 대응한 열을 수정할 수 없습니다
UPDATE
V_JOINEMP V
SET V.DEPT_TITLE = '인사관리부';
5. DISTINCT를 포함한 경우
CREATE OR REPLACE VIEW V_DT_EMP
AS
SELECT DISTINCT E.JOB_CODE
FROM EMPLOYEE E;
- 뷰에 대한 데이터 조작이 부적합합니다
INSERT
INTO V_DT_EMP
(
JOB_CODE
)
VALUES
(
'J9'
);
- 뷰에 대한 데이터 조작이 부적합합니다
UPDATE
V_DT_EMP V
SET V.JOB_CODE = 'J9'
WHERE V.JOB_CODE = 'J7';
- 뷰에 대한 데이터 조작이 부적합합니다
DELETE
FROM V_DT_EMP V
WHERE V.JOB_CODE = 'J7';
6. 그룹 함수나 GROUP BY 절을 포함한 경우
CREATE OR REPLACE VIEW V_GROUPDEPT
AS
SELECT E.DEPT_CODE
, SUM(E.SALARY) 합계
, AVG(E.SALARY) 평균
FROM EMPLOYEE E
GROUP BY E.DEPT_CODE;
- 가상 열은 사용할 수 없습니다
INSERT
INTO V_GROUPDEPT
(
DEPT_CODE
, 합계
, 평균
)
VALUES
(
'D0'
, 60000000
, 4000000
);
- 뷰에 대한 데이터 조작이 부적합합니다
UPDATE
V_GROUPDEPT V
SET V.DEPT_CODE = 'D10'
WHERE V.DEPT_CODE = 'D1';
- 뷰에 대한 데이터 조작이 부적합합니다
DELETE
FROM V_GROUPDEPT V
WHERE V.DEPT_CODE = 'D1';
VIEW 옵션
- OR REPLACE : 기존에 동일한 뷰 이름이 존재하는 경우 덮어쓰고 존재하지 않으면 새로 생성하는 옵션
- FORCE 옵션 : 서브쿼리에 사용 된 테이블이 존재하지 않아도 뷰 생성
CREATE OR REPLACE FORCE VIEW V_EMP
AS
SELECT TCODE
, TNAME
, TCONTENTS
FROM TT;
- NOFORCE 옵션 : 서브쿼리에 테이블이 존재해야만 뷰 생성함(기본값)
CREATE OR REPLACE /*NOFORCE*/ VIEW V_EMP2
AS
SELECT TCODE
, TNAME
, TCONTENTS
FROM TT;
- WITH CHECK OPTION : 조건절에 사용 된 컬럼의 값을 수정하지 못하게 한다.
CREATE OR REPLACE VIEW V_EMP3
AS
SELECT E.*
FROM EMPLOYEE E
WHERE MANAGER_ID = '200'
WITH CHECK OPTION;
- 뷰의 WITH CHECK OPTION의 조건에 위배 됩니다
UPDATE
V_EMP3
SET MANAGER_ID = '900'
WHERE MANAGER_ID = '200';
- WITH READ ONLY : DML 수행이 불가능하게 한다.
CREATE OR REPLACE VIEW V_DEPT
AS
SELECT D.*
FROM DEPARTMENT D
WITH READ ONLY;
- 읽기 전용 뷰에서는 DML 작업을 수행할 수 없습니다.
DELETE
FROM V_DEPT;
'TIL > Oracle(SQL)' 카테고리의 다른 글
[Oracle(SQL)] SYNONYM(동의어), 권한과 ROLE (0) | 2022.01.28 |
---|---|
[Oracle(SQL)] SEQUENCE, INDEX (0) | 2022.01.27 |
[Oracle(SQL)] TCL(Transaction Control Language), DDL(ALTER, DROP) (0) | 2022.01.25 |
[Oracle(SQL)] DML (INSERT, UPDATE, DELETE, TRUNCATE, MERGE) (0) | 2022.01.25 |
[Oracle(SQL)] DDL(CREATE) (0) | 2022.01.25 |